【问题标题】:Can we safely rely on the location of v.end() of iterators?我们可以安全地依赖迭代器的 v.end() 的位置吗?
【发布时间】:2014-03-06 18:01:52
【问题描述】:

对于 STL 中的向量 v,存储 v.end()(例如 vector::iterator)以供以后使用是否安全?是否可以保证以后使用存储的迭代器时,它仍然会指向同一个位置?

考虑以下向量v
1, 2, 3, 4, 5

我现在将 std::vector<int>::iterator it = v.end() 存储起来。稍后,我将 2 个新元素推入向量中,之后它看起来像:
1, 2, 3, 4, 5, 6, 7

我现在可以放心*it == 6了吗?

【问题讨论】:

  • 我在回答中犯了一个小错误,但我更正了。查看编辑后的答案。

标签: c++ vector stl iterator


【解决方案1】:

没有。

在您某些内容到std::vector 之后,end() 迭代器总是无效。

所有其他迭代器都是有效的除非

新的容器大小大于之前的容量


但是,有些容器的迭代器在推送后不会失效。参考this question的优秀答案。


如果您想在 推送 新元素时使用迭代器记住向量中的位置,您可以使用reserve() 会员。

std::vector<int> numbers = {1,2,3};
numbers.reserve(4);
int capacity = numbers.capacity();  // capacity >= 4
std::vector<int>::iterator pos = numbers.begin() + 2 // any iterator before
                                                     // the point of insertion
numbers.push_back(4); // new size is 4, old capacity is >= 4, 
                      // therefore pos is still valid. 

【讨论】:

  • 谢谢,那么在向量中记住位置的唯一方法是使用数组索引来记住位置,如果我要将额外的元素推入向量中?
  • @lwxted 没错。或者使用std::list,其迭代器在推送额外元素后不会失效。
  • 在 C++11 中,迭代器只有在新大小大于旧容量时才会失效。
  • @BrianBi:但是插入点之后的迭代器无论如何也会失效,对吧?并且结束迭代器在任何插入点之后。
  • @MartinDrozdik:过去的结束迭代器 is 总是无效的,那部分是正确的。倒退的是关于其余迭代器的 next 语句。
【解决方案2】:

§ 23.3.6.5/1 [vector.modifiers]

如果新大小大于旧容量,则会导致重新分配。如果没有发生重新分配, 插入点之前的所有迭代器和引用都保持有效。

没有明确说明,但这意味着插入点及其之后的所有迭代器、引用都无效。这包括 end 迭代器。本节专门讨论 insert/push_back,但在涉及擦除等方面仍然或多或少准确。

§ 23.3.6.3/5 [向量.容量]

重新分配使所有引用元素的引用、指针和迭代器无效 在序列中。保证在之后发生的插入期间不会发生重新分配 调用 reserve() 直到插入会使向量的大小大于 capacity() 的值。

【讨论】:

  • 那么只有重新分配才能使向量迭代器失效(在push_back之后)?
  • 所有向量修饰符(insert/erase/push_back/reserve/resize/etc)都可以使向量迭代器失效。将其编辑到帖子中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-18
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
  • 2011-06-16
  • 1970-01-01
  • 2016-04-07
相关资源
最近更新 更多