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

时间:2009-05-27 04:47:15

标签: c++ stl standards deque

我对deque中的迭代器失效感到有点困惑。 (在this问题的背景下)

以下是 - C ++标准库:教程和参考的摘录, 作者Nicolai M. Josuttis

  

任何元素的插入或删除   开头或结尾 以外的   使所有指针,引用无效,   和引用元素的迭代器   deque。

以下是SGI网站摘录:

  

迭代器失效的语义   对于双端队列如下。插入   (包括push_frontpush_back)   使所有引用的迭代器无效   去一个双性人在中间擦除   deque使所有迭代器无效   参考双端队列。擦除   一个双端队列的开头或结尾(包括   pop_frontpop_back)使a。无效   迭代器只有它指向   擦除元素。

恕我直言,deque是块的集合,第一个块在一个方向上生长,最后一个块在相反方向上生长。

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

push_back, push_front不应对deque迭代器产生任何影响(我同意Josuttis的意见)。

正确的解释是什么?标准对此有何看法?

3 个答案:

答案 0 :(得分:13)

来自standard working draft

  

模板< class InputIterator>       void insert(迭代器位置,                       首先是InputIterator,最后是InputIterator);

     

1效果:插入中间   deque使所有的无效   迭代器和对元素的引用   deque。两端都有一个插件   deque使所有的无效   deque的迭代器,但没有   对参考文献有效性的影响   对于双端队列的元素。“

所以两者都是正确的。正如Josuttis指出的那样,在前面或后面插入不会使对deque元素的引用无效,只有 deque本身的迭代器

编辑:more up-to-date draft说的基本相同(第23.2.2.3节)

答案 1 :(得分:12)

  

恕我直言,deque是块的集合,第一个块在一个方向上生长,最后一个块在相反方向上生长。

您的意见是您的特权,但这是错误的。 :)

deque是一个容器语义,但就实现而言,它设计为由一个或多个内存块实现。 C++'s iterator invalidation rules来自实施,所以这就是原因。可以说这是一个小的抽象泄漏,但是,无论如何。

SGI STL文档不适合阅读,因为the SGI STL is not the C++ Standard Library。不幸的是,Josuttis是那些称之为“STL”的人之一,这导致了你的困惑。


  

以下摘录自 - C ++标准库:教程和参考,作者:Nicolai M. Josuttis

     
    

在开头或结尾处插入或删除之外的元素会使引用deque元素的所有指针,引用和迭代器无效。

  

简单地说,来自Josuttis的这篇文章误导暗示在开头或结尾插入或删除 的元素使指针,引用或迭代器无效......虽然值得注意的是他永远不会出来并断言这一点。


以下是std::deque的真实,正确的官方规则:

C ++ 03

  • 插入:所有迭代器和引用都无效,除非插入的成员位于双端队列的末尾(前面或后面)(在这种情况下,所有迭代器都无效,但引用元素不受影响)[23.2.1.3/1]

  • 删除:除非删除的成员位于双端队列的末尾(前面或后面),否则所有迭代器和引用都将失效(在这种情况下,只有迭代器和对已擦除成员的引用)无效)[23.2.1.3/4]

  • 调整大小:根据插入/删除[23.2.1.2/1]

C ++ 11

  • 插入:所有迭代器和引用都无效,除非插入的成员位于双端队列的末尾(前面或后面)(在这种情况下,所有迭代器都无效,但引用元素不受影响)[23.3.3.4/1]

  • 擦除:擦除最后一个元素只会使迭代器和对已擦除元素的引用以及过去的迭代器无效;擦除第一个元素只会使迭代器和对擦除元素的引用无效;擦除所有其他元素会使所有迭代器和引用无效(包括过去的迭代器)[23.3.3.4/4]

  • 调整大小:根据插入/删除[23.3.3.4/1]


进一步阅读

我不确定你还在寻找什么可靠来源 - 相关的标准段落已被引用和引用。

答案 2 :(得分:0)

SGI实现可能使用可增长的数组,因此如果插入导致数组增长,则指向旧数组的迭代器无效。

编辑:

查看C ++编程语言第三版的第17.2.3节,我在deque的描述中没有看到任何指示哪些操作保留或使迭代器无效的内容。我可能正在寻找错误的位置,或者行为可能未定义。