带有deque的随机访问迭代器的无效迭代器

时间:2012-11-20 13:28:27

标签: c++ stl

我正在阅读Scott Meyers的有效STL。在第1项中,作者提到了如何在各种容器中进行选择,下面是我难以理解的文本片段。

  

拥有一个具有随机访问权限的序列容器会有所帮助吗?   迭代器,其中指针和数据引用不是   只要没有删除任何内容并且插入就会失效   只在容器的两端?这是一个非常特殊的情况,但如果   这是你的情况,deque是你梦想的容器。   (有趣的是,插入时deque的迭代器可能会失效   仅在容器的末端制造。 deque是唯一的标准   其迭代器可能无效的STL容器   使其指针和引用无效。)

我对上述文字的疑问

  1. 作者在上面的上下文中用指针和引用表示什么,它与迭代器有什么不同?

  2. 如果仅在结尾插入并且仍然有有效的指针和引用,deque的迭代器如何无效?

  3. 请上面两个问题用简单的例子来回答。

    感谢您的时间和帮助。

2 个答案:

答案 0 :(得分:2)

对于第一部分,这是什么意思:

deque<int> foo(10, 1); // a deque with ten elements with value of 1
int& bar = foo.front(); // reference
int* baz = &foo.front(); // pointer
deque<int>::iterator buz = foo.begin(); // iterator
deque.push_front(0); 
// At this point bar and baz are still valid, but buz may have been invalidated

第二部分详细介绍了这一点:

Why does push_back or push_front invalidate a deque's iterators?

答案 1 :(得分:1)

迭代器通常用于&#34;循环通过&#34;标准库容器的元素,就像使用数组索引一样,例如在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将指向&#34;元素&#34;一个块之后是deque中的最后一个真实元素。如果您尝试执行类似

的操作
*i = 88;

在上面的for循环结束后,这将是一个问题,因为容器没有&#34;拥有&#34;记忆i&#34;点&#34;到。

但迈耶斯可能正在谈论的是,该标准将设计师的大部分实施方案留给了设计师。 Deques 通常实现为包含多个元素的内存块的链接列表,因此与向量不同,不能保证元素在内存中彼此相邻。此外,迭代器必然包含有关这些&#34;块&#34;的信息。这样他们就可以顺利地遍历它们(即迭代器不仅仅是指针)。

例如,如果我push_back()一个新元素,但是&#34; last&#34;大块的内存,然后deque将需要为新元素分配一个新的内存块(以及添加到最后的未来元素)。因为我之前使用的迭代器可能不会#34;知道&#34;关于这个新的记忆块,它可能是无效的。

另一方面,引用和实际指针将在此上下文中用于引用/指向容器中的各个对象。如果我写

int& j = *c.begin();

然后j是对c的第一个元素的引用。如果我那么

c.push_front(74);

j仍引用前一个第一个元素,即使它不再位于双端队列的前面。

然而,如果你在deque的中间中插入一些内容,那么你很可能会有效地分割其中一个连续的内存并试图挤压你的新内存那里的元素。为了腾出空间,一方或另一方的元素必须在内存中混乱(并且可能需要分配新的内存)。这必然会使指针/对该元素上的元素的引用无效&#34; side&#34;插入。由于由实现者决定插入元素的确切空间,所以所有投注都相对于任何指针/引用都是关闭的,无论它在插入方面的位置如何。