C++ 我可以在std::list中移动元素,而不会使迭代器或引用无效,但是如何移动呢?

C++ 我可以在std::list中移动元素,而不会使迭代器或引用无效,但是如何移动呢?,c++,linked-list,stdlist,C++,Linked List,Stdlist,发件人: 添加、删除和移动列表中或多个列表中的元素不会使迭代器或引用无效。迭代器只有在删除相应的元素时才会失效 事实上,对元素进行排序时就是这样。发件人: 此函数与std::sort的另一个不同之处在于,它不要求列表的元素类型可交换,保留所有迭代器的值,并执行稳定排序 但是我如何在保留所有迭代器值的同时任意交换两个元素的位置呢 例如,假设我有一个列表: std::list<int> l({1, 2, 3, 4}); auto it = l.begin(), jt = ++l.begi

发件人:

添加、删除和移动列表中或多个列表中的元素不会使迭代器或引用无效。迭代器只有在删除相应的元素时才会失效

事实上,对元素进行排序时就是这样。发件人:

此函数与
std::sort
的另一个不同之处在于,它不要求列表的元素类型可交换,保留所有迭代器的值,并执行稳定排序

但是我如何在保留所有迭代器值的同时任意交换两个元素的位置呢

例如,假设我有一个列表:

std::list<int> l({1, 2, 3, 4});
auto it = l.begin(), jt = ++l.begin();
但是,尽管
2
将出现在
1
之前,但我不会保留迭代器的值,因为它显然将指向
2

鉴于上述引用,我认为应该有可能实现我想要实现的目标;但是怎么做呢

编辑:让事情变得清楚:再举一个例子:

std::list<int> l({2, 1, 3, 4, 5});
auto it = l.begin(), jt = ++l.begin();
现在列表的顺序是:
1,2,3,4,5
,但是
它仍然指向
2
jt
仍然指向
1


另一方面,
std::swap(it,jt)
std::swap(*it,*jt)
没有我想要的语义。调用其中任何一个将使
it
指向
1
jt
指向
2
。()

您正在交换值。不是迭代器值。因此迭代器保持不变,而它们所指向的值发生更改(交换)

想想迭代器,比如指针,至少在这方面是这样的


因此,交换迭代器和值的方法是:

std::swap(*it, *jt);
std::swap(it, jt);
但是我如何在保留所有迭代器值的同时任意交换两个元素的位置呢

按照@cpplearner的建议,使用

它可以对单个元素或范围进行操作。它还可以跨列表传输元素

下面是一个简单的示例,演示如何移动单个元素

std::list<int> list{1,2,3,4,5};

// This element will be moved
auto source = std::find(list.begin(), list.end(), 4);

// It will be inserted before this element
auto destination = std::find(list.begin(), list.end(), 2);

list.splice(destination, list, source);
// ^                      ^
// |                      `- A list to move from
// `- A list to move to   

// Prints `1 4 2 3 5`.
for (int it : list) std::cout << it << ' ';
std::list{1,2,3,4,5};
//此元素将被移动
auto source=std::find(list.begin(),list.end(),4);
//它将插入此元素之前
自动目的地=std::find(list.begin(),list.end(),2);
列表.拼接(目的地、列表、源);
// ^                      ^
//|`-要从中移动的列表
//`-要移动到的列表
//打印“1 4 2 3 5”。

对于(int-it:list)std::cout,它是一个双链接列表。移动元素时,只需调整相邻元素之间的指针。交换时,双链接列表中的元素不会“移动”。它们指向下一个和上一个元素的指针会改变instead@HenriMenke如果我自己实现一个双链表,那就很简单了;但是如何使用
std::list
?看看维基百科上关于“双链接列表”的文章,你会明白它是如何工作的,你会发现自己是如何做到的。OP问的是如何使用
std::list
,而不是为什么可能。我明白了。我将更改我的答案。“因此,交换迭代器和值的方法是:std::swap(*it,*jt);std::swap(it,jt);”测试。不工作。他想改变元素的顺序。这不行。@SidS OP想通过调整内部指针而不是交换内容来利用链表的特殊属性对元素重新排序。谢谢。我必须说,一开始我对“将元素从一个列表转移到另一个列表”感到困惑。因此,我的第一印象是,使用splice在同一列表中移动元素可能是某种UB。然而,值得注意的是,在复杂性分析中,CPPPreference明确提到了拼接可能用于一个列表,而不是两个列表,并且它似乎在实践中起作用()
std::swap(*it, *jt);
std::swap(it, jt);
std::list<int> list{1,2,3,4,5};

// This element will be moved
auto source = std::find(list.begin(), list.end(), 4);

// It will be inserted before this element
auto destination = std::find(list.begin(), list.end(), 2);

list.splice(destination, list, source);
// ^                      ^
// |                      `- A list to move from
// `- A list to move to   

// Prints `1 4 2 3 5`.
for (int it : list) std::cout << it << ' ';