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

invalid iterator with random access iterators with deque

本文关键字:迭代器 无效 访问 随机 deque 具有      更新时间:2023-10-16

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

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

我对以上文本的问题

  1. 作者在上面的上下文中所说的指针和引用是什么意思?它和迭代器有什么不同?

  2. 当插入仅在末尾,而我们仍然有有效的指针和引用时,deque的迭代器是如何无效的?

请用简单的例子回答以上两个问题。

谢谢你的时间和帮助。

对于第一部分,其含义是:

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

对于第二部分,这里已经详细介绍了它:

为什么push_back或push_front会使deque';s迭代器?

迭代器通常用于"循环遍历"标准库容器的元素,就像使用数组索引一样,例如在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中最后一个实元素后一个块的"元素"。如果你试着做一些类似的事情

*i = 88;

就在上述for循环结束后,这将是一个问题,因为容器不"拥有"i"指向".的内存

但Meyers可能在谈论的是,该标准将deque的大部分实现留给了设计师。Deques通常被实现为包含多个元素的内存块的链表,因此与向量不同,无法保证元素在内存中相邻。此外,迭代器必须包含关于这些"块"的信息,以便它们能够顺利地遍历它们(即迭代器不仅仅是指针)。

例如,如果我push_back()一个新元素,但"最后"块内存中没有更多空间,那么deque将需要为新元素(以及添加到末尾的未来元素)分配一个新的内存块。由于我以前使用的迭代器可能不"知道"这个新的内存块,所以它可能是无效的。

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

int& j = *c.begin();

则j是对CCD_ 7的第一元素的引用。如果我做

c.push_front(74);

j仍然引用以前的第一个元素,即使它不再位于deque的前面。

但是,如果你在deque的中间插入了一些东西,那么很可能你正在有效地分割其中一个连续的内存块,并试图在其中挤压你的新元素。为了腾出空间,必须在内存中来回移动一侧或另一侧的元素(并且可能需要分配新的内存)。这必然会使指向插入"一侧"元素的指针/引用无效。由于如何为插入的元素留出确切的空间取决于实现者,因此对于任何指针/引用,无论其相对于插入位于何处,所有赌注都是无效的。