繁体   English   中英

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

[英]invalid iterator with random access iterators with deque

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

如果有一个带有随机访问迭代器的序列容器,只要没有删除任何内容并且插入只发生在容器的末尾,那么指针和数据引用是否有效会不会有帮助? 这是一个非常特殊的情况,但如果是你的情况,deque是你梦想的容器。 (有趣的是,当只在容器的末端进行插入时,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的迭代器无效?

迭代器通常用于“循环”标准库容器的元素,就像使用数组索引一样,例如在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 “指向”的内存。

但迈耶斯可能正在讨论的是,该标准版为设计师留下了很多deque的实现。 Deques 通常被实现为包含多个元素的内存块的链接列表,因此与向量不同,不能保证元素在内存中彼此相邻。 此外,迭代器必然包含有关这些“块”的信息,以便它们可以平滑地遍历它们(即迭代器不仅仅是指针)。

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

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

int& j = *c.begin();

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

c.push_front(74);

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

但是 ,如果你在双端队列中间插入一些东西,那么你很可能会有效地分裂其中一个连续的内存块并尝试在那里挤压你的新元素。 为了腾出空间,一方或另一方的元素必须在内存中混乱(并且可能需要分配新的内存)。 这必然会使插入的“侧”上的元素的指针/引用无效。 由于由实现者决定插入元素的确切空间,所以所有投注都相对于任何指针/参考都是关闭的,无论它在插入方面的位置如何。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM