【问题标题】:C++ deque: when iterators are invalidatedC ++ deque:当迭代器无效时
【发布时间】:2012-05-09 13:55:31
【问题描述】:

如果我错了,请纠正我。谢谢!

inserterase 将重定位元素,但插入/擦除位置之前的元素不会重定位,因此它们的迭代器仍然有效。

push_backpop_back 不会使任何迭代器失效。

push_frontpop_front 使所有迭代器无效。

swap 不会重定位元素,但不知何故我认为它应该使迭代器无效。

【问题讨论】:

  • @dirk 这显然是一个真实的问题,并且有一个非常具体的答案。简单不代表没有优点。
  • 注意 std::<emphasis>list</emphasis>.insert() 不会使迭代器失效

标签: c++ stl iterator deque


【解决方案1】:

push_back()push_front() 是根据insert() 定义的。同样,pop_back()pop_front() 是根据erase() 定义的。

以下是 C++03 标准关于 insert() (23.2.1.3/1) 的迭代器失效的说明:

双端队列中间的插入使所有迭代器无效,并且 对双端队列元素的引用。在任一端插入 deque 使 deque 的所有迭代器无效,但对 deque 没有影响 对双端队列元素的引用的有效性。

所以push_front()push_back() 使迭代器无效,但对元素本身的引用仍然有效。

对于任一端的erase() (23.2.1.3/4):

双端队列中间的擦除使所有迭代器和 对双端队列元素的引用。在任一端擦除 deque 仅使迭代器和对已擦除对象的引用无效 元素。

所以pop_front()pop_back() 只会使迭代器/对相关元素的引用无效。

据说这是关于任何标准容器的swap()(23.1/10“容器要求”):

没有 swap() 函数会使任何引用、指针或迭代器无效 指被交换的容器的元素。

C++11 添加了以下关于end() 迭代器在deque 上的行为对这些操作的行为的说明。基本上,end() 的迭代器应该在swap() 之后或在删除deque 中的最后一个元素之后被视为无效:

擦除双端队列的最后一个元素的擦除操作只会使过去的迭代器以及所有迭代器和对被擦除元素的引用无效。

在交换之前引用一个容器中的元素的每个迭代器都应该在交换之后引用另一个容器中的相同元素。未指定在交换之前具有值 a.end() 的迭代器在交换之后是否具有值 b.end()。

我认为,即使您尚未使用 C++11 编译器,也可以按照这些规则适用的方式进行编码。

【讨论】:

  • 你知道迭代器的“失效”究竟是什么吗?例如,deque::swap 是否合法(假设)使迭代器不能再被推进,但仍然能够被取消引用?
猜你喜欢
  • 1970-01-01
  • 2020-09-24
  • 2020-02-29
  • 2021-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多