在列表内或跨多个列表添加、删除和移动元素不会使迭代器或引用无效。只有当相应的元素被删除时,迭代器才会失效。
事实上,排序元素时就是这种情况。来自cppreference 文章std::list::sort
:
该函数的不同之处还在于
std::sort
它不需要列表的元素类型是可交换的,保留所有迭代器的值,并执行稳定的排序。
但是如何在保留所有迭代器的值的同时任意交换两个元素的位置?
例如,假设我有一个列表:
std::list<int> l({1, 2, 3, 4});
auto it = l.begin(), jt = ++l.begin();
Run Code Online (Sandbox Code Playgroud)
现在it
指向1
和jt
指向2
。我可以重新排列这个列表,使之2
出现在之前1
,但it
仍指向1
吗?
我可以:
std::swap(*it, *jt);
Run Code Online (Sandbox Code Playgroud)
但是,虽然2
会在 之前1
,我不会保留迭代器的值,因为显然it
会指向2
.
鉴于 cppreference 的前面引用,我想应该有可能实现我想要实现的目标;但是怎么样?
编辑:为了清楚起见:再举一个例子:
std::list<int> l({2, 1, 3, 4, 5});
auto it = l.begin(), jt = ++l.begin();
Run Code Online (Sandbox Code Playgroud)
现在it
指向2
和jt
指向1
。
std::list::sort
具有我正在寻找的语义:
l.sort();
Run Code Online (Sandbox Code Playgroud)
现在列表的顺序是:1, 2, 3, 4, 5
,但是it
仍然指向2
并且jt
仍然指向1
。
另一方面,std::swap(it, jt)
也std::swap(*it, *jt)
没有我想要的语义。调用它们中的任何一个都会it
指向1
和jt
指向2
。(ideone证明)
但是如何在保留所有迭代器的值的同时任意交换两个元素的位置?
按照@cpplearner 的建议,使用.splice()
.
它可以对单个元素或范围进行操作。它还可以跨列表传输元素。
这是一个演示如何移动单个元素的简单示例。
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 << ' ';
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2598 次 |
最近记录: |