当没有重新分配时,vec.nd()的迭代器在vec.push_back()之后仍然有效

时间:2011-03-22 19:21:15

标签: c++ iterator

此示例代码有效吗?

#include<vector>
using namespace std;

int main() {
  vector<int> vec(10); // create with 10 elements
  vec.reserve(100);    // set capacity to 100
  vector<int>::iterator iter = vec.end(); // points 1 past vec[9]

  vec.push_back( 777 );

  bool is_this_valid_and_true =  *iter == vec[10]; // ?

  // VS2010 runtime error in debug build:
  // Expression: vector iterator not dereferencable
  // Works in release build

  iter = vec.end() + 1; // points 2 past vec[10]?
  vec.push_back( 888 );
  vec.push_back( 999 );

  is_this_valid_and_true =  *iter == vec[12]; // ?
}

VS2010中的错误可能与此bug有关。

如果我设置命令行选项/D_HAS_ITERATOR_DEBUGGING=0或设置

#define _HAS_ITERATOR_DEBUGGING 0
#include<vector>

没有错误。

修改

根据答案,我认为此代码应该导致错误。编译器中没有错误。它只能在发布模式下工作,因为迭代器是作为指针实现的。

2 个答案:

答案 0 :(得分:7)

23.2.4.3/1:

  

如果新大小为,则会导致重新分配   大于旧容量。如果不   所有的重新分配都发生了   迭代器和引用之前   插入点仍然有效。如果   抛出异常而不是by   复制构造函数或赋值   T的操作符没有效果。

所以不,end()push_back之后无效。引用与vector.insert有关,push_back是根据insert

定义的

答案 1 :(得分:6)

您正在考虑将迭代器作为指针。

迭代器可能会使用指针作为实现细节,但它们不是实际的指针。

因此:

iter = vec.end() + 1; // This is not valid.

没有两个元素通过数据末尾。

vec.end()返回一个迭代器,当递减是对最后一个元素的引用时(假设有元素)。虽然在递增时引用最后一个元素的迭代器等同于end()返回的迭代器。

// Note: Assuming vector iterators were not invalidated after an insert anyway.
//       But for arguments sake lets play this out.
//
vector<int>::iterator iter = vec.end(); // points 1 past vec[9]
vec.push_back( 777 );
bool is_this_valid_and_true =  *iter == vec[10]; // Not valid.
                                                 // This is the end() iterator
                                                 // de-referencing it is UB

但是,取消引用由end()表示的迭代器是未定义的行为()(即使你有保留空间)(实现可能没有使用指针。例如,一些DeBug STL实现将进行大量的错误检查迭代器代码)。