以下是我正在查看的代码段:
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”在这种情况下仍然有效,即使我没有在循环中篡改它,也当向量的容量发生变化时。
那么,“mid”在重新分配后如何能够自我更新?
要知道mid是否完全改变,我将代码中的第4行更改为:
iv.insert(iter, -1); // Did not assign it back to iter.
在中间打印取消引用该值的结果表示该更改,也可能是该消息无效。 (如果我错了,请再次纠正我。)
答案 0 :(得分:3)
您的理解是正确的。一旦容量增加,任何迭代器都将变为无效。 mid
迭代器即使在容量没有变化时变得无效,但它基本上指向前一个元素。
因此原始代码至少可以用于iter
,但mid
在首次插入时将无法使用。通过修改,代码完全无效。
通常vector
迭代器的实现只是一个指向某个元素到支持数组的简单指针。因此,当容量更改并重新分配数组时,任何此类迭代器都不再有效,因为指针指向不再有效的内存。因此,您可能会看到垃圾,您可能会出现分段错误或随机查看正确的值。当容量没有改变时,数组中的元素可以向前移动,这样你就可以在插入点之后看到迭代器中的前一个元素,但仅在数组开头没有空元素的情况下(例如{{1}大于零)。但所有这些都是具体的实施,因此标准明确规定上述大多数是未定义的行为。