简体   繁体   English

在deque中对迭代器失效的困惑

[英]Confusion on iterators invalidation in deque

I'm bit confused regarding iterator invalidation in deque. 关于deque中的迭代器失效,我有点困惑。 (In the context of this question) (在这个问题的背景下)

Following is the excerpts from -- The C++ Standard Library: A Tutorial and Reference, By Nicolai M. Josuttis 以下是摘自 - The C ++标准库:教程和参考,作者:Nicolai M. Josuttis

Any insertion or deletion of elements other than at the beginning or end invalidates all pointers, references, and iterators that refer to elements of the deque. 开头或结尾之外的任何元素的插入或删除都会使引用双端队列元素的所有指针,引用和迭代器无效。

Following is the excerpts from SGI site: 以下是SGI网站的摘录:

The semantics of iterator invalidation for deque is as follows. deque的迭代器失效的语义如下。 Insert (including push_front and push_back ) invalidates all iterators that refer to a deque. Insert(包括push_frontpush_back )使引用deque的所有迭代器无效。 Erase in the middle of a deque invalidates all iterators that refer to the deque. 在双端队列中间擦除使所有引用双端队列的迭代器无效。 Erase at the beginning or end of a deque (including pop_front and pop_back ) invalidates an iterator only if it points to the erased element. 在双端队列的开头或结尾处擦除(包括pop_frontpop_back )只有在指向已擦除元素时才会使迭代器无效。

IMHO, deque is collection of blocks with first block growing in one direction and the last block in opposite direction. 恕我直言,deque是块的集合,第一个块在一个方向上生长,最后一个块在相反方向上生长。

  -   -  -  
  -   -  -
  |   -  -  ^
  |   -  -  |
  V   -  -  |
      -  -  -
      -  -  -

push_back, push_front should not have any impact on deque iterators ( I agree with Josuttis). push_back, push_front不应该对deque迭代器产生任何影响(我同意Josuttis)。

What is the correct explanation? 什么是正确的解释? what the standard say on this? 标准对此有何看法?

From the standard working draft 标准的工作草案

template < class InputIterator > void insert ( iterator position , InputIterator first , InputIterator last ); template <class InputIterator> void insert(iterator position,InputIterator first,InputIterator last);

1 Effects: An insert in the middle of the deque invalidates all the iterators and references to elements of the deque. 1效果:deque中间的插入使所有迭代器和对deque元素的引用无效。 An insert at either end of the deque invalidates all the iterators to the deque, but has no effect on the validity of references to elements of the deque." 在deque两端的插入使deque的所有迭代器无效,但对deque元素的引用的有效性没有影响。“

So both are correct. 所以两者都是正确的。 As Josuttis indicates, insertion at the front or back doesn't invalidate references to elements of the deque, only iterators to the deque itself . 正如Josuttis指出的那样,在前面或后面插入并不会使对deque元素的引用无效,只会对deque本身进行迭代。

EDIT: A more up-to-date draft says essentially the same thing (section 23.2.2.3) 编辑: 更新的草案基本上是相同的(第23.2.2.3节)

IMHO, deque is collection of blocks with first block growing in one direction and the last block in opposite direction. 恕我直言,deque是块的集合,第一个块在一个方向上生长,最后一个块在相反方向上生长。

Your opinion is your prerogative, but it's wrong. 你的意见是你的特权,但这是错的。 :) :)

deque is such a container semantically , but in terms of implementation it's designed to be implemented by one or more blocks of memory. deque语义上是这样的容器,但在实现方面,它被设计为由一个或多个内存块实现。 C++'s iterator invalidation rules come from implementation, so this is why. C ++的迭代器失效规则来自实现,所以这就是原因。 Arguably this is a small abstraction leak but, well, whatever. 可以说这是一个小的抽象泄漏,但是,无论如何。

The SGI STL documentation is not the proper documentation to read, because the SGI STL is not the C++ Standard Library . SGI STL文档不是正确的文档,因为SGI STL不是C ++标准库 Unfortunately, Josuttis is one of those people who calls it "the STL", and this has led to your confusion. 不幸的是,Josuttis是那些称之为“STL”的人之一,这导致了你的困惑。


Following is the excerpts from -- The C++ Standard Library: A Tutorial and Reference, By Nicolai M. Josuttis 以下是摘自 - The C ++标准库:教程和参考,作者:Nicolai M. Josuttis

Any insertion or deletion of elements other than at the beginning or end invalidates all pointers, references, and iterators that refer to elements of the deque. 开头或结尾之外的任何元素的插入或删除都会使引用双端队列元素的所有指针,引用和迭代器无效。

Put simply, this passage from Josuttis is misleading in implying that the insertion or deletion of elements that are at the beginning or end do not invalidate pointers, references or iterators … though it's worth noting that he never comes out and asserts this outright. 简单地说,从约祖蒂斯这段话在暗示被误导认为在开头或结尾, 坏指针,引用或迭代器......虽然这是值得注意的是,他从来没有出来,并声称这完全元素的插入或删除。


Here are the real, proper, official rules for std::deque : 以下是std::deque的真实,正确的官方规则:

C++03 C ++ 03

  • Insertion : all iterators and references are invalidated, unless the inserted member is at an end (front or back) of the deque (in which case all iterators are invalidated, but references to elements are unaffected) [23.2.1.3/1] 插入 :所有迭代器和引用都是无效的,除非插入的成员位于双端队列的末尾(前面或后面)(在这种情况下,所有迭代器都无效,但对元素的引用不受影响)[23.2.1.3/1]

  • Erasure : all iterators and references are invalidated, unless the erased members are at an end (front or back) of the deque (in which case only iterators and references to the erased members are invalidated) [23.2.1.3/4] 擦除 :所有迭代器和引用都无效,除非擦除的成员位于双端队列的末尾(前面或后面)(在这种情况下,只有迭代器和对擦除成员的引用无效)[23.2.1.3/4]

  • Resizing : as per insert/erase [23.2.1.2/1] 调整大小 :按插入/删除[23.2.1.2/1]

C++11 C ++ 11

  • Insertion : all iterators and references are invalidated, unless the inserted member is at an end (front or back) of the deque (in which case all iterators are invalidated, but references to elements are unaffected) [23.3.3.4/1] 插入 :所有迭代器和引用都是无效的,除非插入的成员位于双端队列的末尾(前面或后面)(在这种情况下,所有迭代器都无效,但对元素的引用不受影响)[23.3.3.4/1]

  • Erasure : erasing the last element invalidates only iterators and references to the erased elements and the past-the-end iterator; 擦除 :擦除最后一个元素只会使迭代器和对擦除元素的引用以及过去的迭代器无效; erasing the first element invalidates only iterators and references to the erased elements; 擦除第一个元素只会使迭代器和对擦除元素的引用无效; erasing any other elements invalidates all iterators and references (including the past-the-end iterator) [23.3.3.4/4] 擦除任何其他元素会使所有迭代器和引用无效(包括过去的迭代器)[23.3.3.4/4]

  • Resizing : as per insert/erase [23.3.3.4/1] 调整大小 :按插入/删除[23.3.3.4/1]


Further reading 进一步阅读

I'm not sure what further reference to credible sources you're looking for — the relevant standard passage has already been cited and quoted. 我不确定你还在寻找可靠来源的进一步参考 - 相关的标准段落已被引用和引用。

The SGI implementation probably uses a growable array, so if an insert causes the array to grow, the iterators pointing to the old array are invalid. SGI实现可能使用可增长的数组,因此如果插入导致数组增长,则指向旧数组的迭代器无效。

EDIT: 编辑:

Looking in section 17.2.3 of The C++ Programming Language Third Edition, I don't see anything in the description of deque that indicates what operations preserve or invalidate iterators. 查看C ++编程语言第三版的第17.2.3节,我在deque的描述中没有看到任何表明操作保留或使迭代器无效的内容。 I may be looking in the wrong spot or the behavior may be undefined. 我可能正在寻找错误的位置或行为可能未定义。

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

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