是行为的 std::distance
未定义,当调用一对 std::vector
迭代器,这些迭代器因移动了 vector
?
对于上下文:我正在为一个类编写复制和移动构造函数,这个类有一个 vector
的数据和一个 vector
的迭代器,指向该数据。一旦我将数据移动到目的地,我需要将迭代器的向量翻译成指向新的容器。我希望避免在内存中创建中间索引表示。
的行为是
std::distance
未定义,当调用一对std::vector
迭代器,这些迭代器因移动了vector
?
如果迭代器在移动前是有效的,那么在移动后它们将继续有效--所以你不需要使用 std::distance
.
(着重说明)
容器移动构造后,引用、指针。和迭代器 迭代器以外)到
other
仍然有效,但指的是现在在的元素。*this
.目前的标准是通过以下的空白声明来保证的。[容器.要求.一般12]目前正在考虑通过以下方式提供更直接的担保 LWG 2321.
[容器.要求.一般12] 指出
除非另有规定(无论是显式的还是用其他函数定义的),否则调用容器成员函数或将容器作为参数传给库函数 不得使迭代器无效 的值,或改变该容器内对象的值。
同样的空白语句也适用于移动赋值操作符,这意味着,根据标准,迭代符 会 搬迁后继续有效。
目前的措辞是 LWG 2321 给出了一个提示,如果库工作组最终确定这个标准中的新段落会是什么样子--这似乎很难。LWG 2321早在2013年就开始了。
没有移动构造函数(或移动赋值操作符,当
allocator_traits<allocator_type>::propagate_on_container_move_assignment::value
是true
)的容器(除了array
)使任何指向源容器元素的引用、指针或迭代器无效。[注: 该项end()
迭代器并不指向任何元素,所以它可能无效。— 尾注]
如果太含糊,你可以使用
无
swap()
函数使任何引用、指针无效。或迭代器 指的是被交换的容器的元素。[ 注:end()
迭代器没有引用任何元素,所以可能无效。- 尾注 ]
如果迭代器有效 之前 你 swap
,它们是有效的 之后 的 swap
.
下面是一个使用给定的保证的示例类 swap
:
#include <vector>
class Foo {
std::vector<int> data{};
std::vector<decltype(data)::iterator> dits{};
public:
Foo() = default;
Foo(const Foo&) = delete; // here, dits would need to be calculated
// A move constructor guaranteed to preserve iterator validity.
Foo(Foo&& rhs) noexcept {
data.swap(rhs.data);
dits.swap(rhs.dits);
}
Foo& operator=(const Foo&) = delete;
// A move assignment operator guaranteed to preserve iterator validity.
Foo& operator=(Foo&& rhs) noexcept {
data.swap(rhs.data);
dits.swap(rhs.dits);
return *this;
}
~Foo() = default;
};