[英]Arithmetic on invalidated iterators
当调用一对已通过移动vector
无效的std::vector
迭代器时, std::distance
的行为是否未定义?
对于上下文:我正在为具有数据vector
和指向该数据的迭代器vector
的 class 编写复制和移动构造函数。 将数据移动到目的地后,我需要转换迭代器向量以指向新容器。 我想避免在 memory 中创建中间索引表示。
当调用一对已通过移动
vector
无效的std::vector
迭代器时,std::distance
的行为是否未定义?
如果迭代器在移动之前有效,则它们在移动之后将保持有效 - 因此您无需使用std::distance
重新计算它们。
(下面强调我的)
在容器移动构造之后,指向
other
的引用、指针和迭代器(除了结束迭代器)仍然有效,但引用现在位于*this
中的元素。当前标准通过[container.requirements.general/12]中的一揽子声明做出此保证,并且正在考虑通过LWG 2321提供更直接的保证。
[container.requirements.general/12]指出
Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iterators to, or change the values of, objects within that container .
移动赋值运算符也有相同的总括语句,这意味着根据标准,迭代器在移动后将保持有效。
LWG 2321中的当前措辞暗示了如果图书馆工作组最终确定标准中的新段落会是什么样子——这似乎很难。 LWG 2321 于 2013 年开业。
容器(
array
除外)的任何移动构造函数(或当allocator_traits<allocator_type>::propagate_on_container_move_assignment::value
为true
时移动赋值运算符)会使引用源容器元素的任何引用、指针或迭代器无效。 [注意:end()
迭代器不引用任何元素,因此它可能会失效。 ——尾注]
如果这太模糊,您可以使用
[container.requirements.general/11.6]
no
swap()
function 使任何引用被交换容器元素的引用、指针或迭代器无效。 [ 注意:end()
迭代器不引用任何元素,因此它可能会失效。 ——尾注]
如果迭代器在您swap
之前有效,则它们在swap
之后有效。
这是一个示例 class 使用为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;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.