迭代器如何在向量重新分配后更新

How do iterators update after vector reallocation

本文关键字:分配 更新 新分配 向量 迭代器      更新时间:2023-10-16

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

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]迭代器无效规则

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

那么,"mid"如何在重新分配后更新自身呢?

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

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

在mid处打印取消引用值的结果表明发生了更改,也许iter也无效。(再次,如果我错了,请纠正我)。

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

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

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