迭代器通常用于“循环”标准库容器的元素,就像使用数组索引(例如,在for
循环中。
由于多种原因,迭代器可能无效。其中发生这种情况的一个常见的情况是当使用for
环如以下:
std::deque<int> c;
for(std::deque<int>::iterator i = c.begin(); i != c.end(); ++i) {
// do some stuff to the deque's elements here
}
在上述循环的结尾,迭代器i
将最后后指向一个“元件”一个块deque中的真实元素。如果你尝试了上述for
循环,因为容器不“拥有”内存i
“点”到这将是一个问题结束后有权这样做
*i = 88;
。
但是,梅耶斯可能会谈论的是,该标准留下了许多向设计师开放的实现。 Deques是通常是实现为拥有多个元素的内存块的链接列表,因此不像向量那样保证元素在内存中彼此相邻。此外,迭代器必须包含关于这些“块”的信息,以便它们可以平滑地遍历它们(即迭代器不仅仅是指针)。例如,如果我push_back()
一个新的元素,但在“最后”的内存块中没有更多的空间,那么双转移将需要为新元素分配一个新的内存块(以及未来元素添加到结束)。由于我以前使用的迭代器可能不会“知道”这块新的内存,因此它可能是无效的。
另一方面,引用和实际指针将在此上下文中引用/指向容器中的单个对象。如果我写
int& j = *c.begin();
然后j是对第一个元素c
的引用。如果我再做
c.push_front(74);
j
还引用了以前的第一要素,即使它不再在双端队列的前面。
然而,如果插入双端队列中间的东西,那么很可能你被有效分裂的记忆那些连续块之一,要挤你的新的元素在里面。为了腾出空间,一方或另一方的元素必须在内存中进行洗牌(并且可能需要分配新的内存)。这必然会使插入的“侧”上的元素的指针/引用无效。由于要由实施者决定插入元素的确切空间,因此无论指向/插入的位置如何,所有投注都关闭。
在开头或结尾插入不会更改内容的实际内存位置,因此任何指针或引用都将继续指向正确的对象。但是,如果迭代器存储为从头开始的偏移量,插入操作将使任何现有的迭代器都具有错误的偏移量。然而,这是一个完全的猜测,只是大声思考。 – BoBTFish
[为什么push \ _back或push \ _front使一个deque的迭代器失效?](http://stackoverflow.com/questions/913070/why-does-push-back-or-push-front-invalidate-a -deques-iterators) – jrok