我可以在 std::list 中移动元素而不会使迭代器或引用无效,但是如何移动呢?
I can move elements within the std::list without invalidating iterators nor references, but how?
来自 cpppreferences 文章 onstd::list
:
在列表中或跨多个列表添加、删除和移动元素不会使迭代器或引用失效。仅当删除相应的元素时,迭代器才会失效。
事实上,在对元素进行排序时就是这种情况。来自 cpp偏好文章 关于std::list::sort
:
此函数与
std::sort
函数的不同之处在于,它不要求列表的元素类型可交换,保留所有迭代器的值,并执行稳定的排序。
但是,如何在保留所有迭代器的值的同时任意交换两个元素的位置呢?
例如,假设我有一个列表:
std::list<int> l({1, 2, 3, 4});
auto it = l.begin(), jt = ++l.begin();
现在it
指向1
,jt
指向2
。我可以重新排序此列表,以便2
排在1
之前,但it
仍然指向1
?
我可以做:
std::swap(*it, *jt);
但是,虽然2
将在1
之前出现,但我不会保留迭代器的值,因为显然it
会指向2
。
鉴于上述来自cpp偏好的引用,我想应该有可能实现我想要实现的目标;但是如何实现呢?
编辑:为了弄清楚事情:再举一个例子:
std::list<int> l({2, 1, 3, 4, 5});
auto it = l.begin(), jt = ++l.begin();
现在it
指向2
,jt
指向1
。
std::list::sort
具有我正在寻找的语义:
l.sort();
现在列表的顺序是:1, 2, 3, 4, 5
,但是it
仍然指向2
,jt
仍然指向1
。
另一方面,std::swap(it, jt)
norstd::swap(*it, *jt)
没有我想要的语义。打电话给他们中的任何一个都会使it
指向1
,jt
指向2
。(鉴定)
但是,如何在保留所有迭代器值的同时任意交换两个元素的位置呢?
按照@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 << ' ';
您正在交换值。 不是迭代器值。 因此,迭代器保持不变,而它们指向的值会发生变化(被交换)。
至少在这方面,请考虑像指针这样的迭代器。
因此,交换迭代器和值的方法就是:
std::swap(*it, *jt);
std::swap(it, jt);
- 将对象移动到std::shared_ptr
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 何时在引用或唯一指针上使用移动语义
- 无法访问嵌套类.类的使用无效
- 如何从具有移动语义的类对象中生成共享指针
- 将shared_ptr移动到<StructA>shared_ptr<变体<结构A、结构 B>>
- C / C++ 移位/偏移/向左或向右移动位图?
- MSVC将仅移动结构参数解释为指针
- 如果用户输入无效,如何使用字符串变量-C++重复输入命令
- 自定义先决条件对移动分配运算符有效吗
- 返回值优化:显式移动还是隐式
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 移动构造函数是否使shared_from_this无效
- C 11移动无效
- 我可以在 std::list 中移动元素而不会使迭代器或引用无效,但是如何移动呢?
- 移动语义:从"类型&&"到"类型"的转换无效。模板:将未知参数传递给重载函数
- 使用 CSplitterWindowImpl 处理移动并使子窗格无效
- std::list-是在移动时无效的迭代器
- 条件跳转或移动取决于未初始化的值和大小的无效写入
- 捕获和调试对移动lambda内部局部变量引用的无效使用