c++ - vector 重新分配后迭代器如何更新

标签 c++ c++11 stl iterator

这是我正在查看的代码片段:

vector<int> iv = {1,2,3,4,5,6,7,8,9,10};
auto iter = iv.begin(), mid = iv.begin() + iv.size()/2;
for(int count = 100; count; --count ) {
    iter = iv.insert(iter, - 1);
    cout << "capacity = " << iv.capacity() << "*mid = " << *mid << endl;

}

根据迭代器失效规则:
vector:插入点之前的所有迭代器和引用不受影响,除非新容器大小大于以前的容量(在这种情况下所有迭代器和引用都无效)[23.2.4.3/1] Iterator invalidation rules

我明白,由于我在每次插入操作时重新分配“iter”的值,也许我能够保持它的有效性(如果我错了请纠正我)。但是,在这种情况下,迭代器“mid”仍然有效,即使我没有在循环中篡改它,而且当 vector 的容量发生变化时也是如此。

那么,“mid”如何在重新分配后自行更新?

为了知道 mid 是否发生了变化,我将代码中的第 4 行更改为:

iv.insert(iter, -1); // Did not assign it back to iter.

打印取消引用 mid 值的结果表明发生了变化,也许还表明 iter 已失效。 (再一次,如果我错了,请纠正我)。

最佳答案

你的理解是正确的。一旦容量增加,任何迭代器都会失效。 mid 迭代器变得无效,即使容量没有改变但它基本上指向前一个元素。

因此原始代码至少对 iter 有效,但是 mid 在第一次插入时将变得不可用。修改后的代码完全无效。

通常 vector 迭代器的实现只是一个简单的指针,指向支持数组的某个元素。因此,当容量发生变化并重新分配数组时,任何此类迭代器都不再有效,因为指针指向不再有效的内存。结果,您可能会看到垃圾,您可能会遇到段错误或随机看到正确的值。当容量不变时,数组中的元素可能会向前移动,因此您可以在插入点之后看到迭代器中的前一个元素,但前提是数组开头没有空元素(例如 start 大于零)。但所有这些都是特定于实现的,因此标准明确规定上述大部分是未定义的行为

关于c++ - vector 重新分配后迭代器如何更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36300745/

相关文章:

c++ - 使用 QNetwork 时的奇怪警告

c++ - 如何将 unique_ptr 与 std::copy 一起使用?

c++ - ROS 订阅回调 - 使用 boost::bind 和成员函数

c++ - 关于C++模板语法的一个问题(STL库源码)

c++ - 获取位于特定区间内的已排序值列表的子列表的最短方法

c++ - 使用 CMake 为 C++ 构建协议(protocol)

javascript - 如何使用 IWebBrowser2 修复应用程序中的 JavaScript 错误?

c++ - 重载运算符 |干扰 Qt 枚举常量

c++ - 通过指定成员的值删除 `std::set` 的成员

c++ - 如何打破循环以在 C++ 中获取整数数组