使用向量(STL)时未定义的行为,请在原因后面解释下面的代码输出

时间:2017-12-05 10:01:30

标签: c++ vector stl

这个可能适用于某些编译器/操作系统,并与其他人崩溃。与" List"相同的代码它工作正常,使用" vector"只有我面临未定义的行为输出。 STL(矢量)是安全的??

注意:这不是一个实时代码,我只是通过一些示例程序来实现它。

#include <vector>
#include <iostream>

using namespace std;

int main() {
  vector<int> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);
  v.push_back(4);
  for (vector<int>::iterator i = v.begin();
       i != v.end(); i++) {
    cout << *i << endl;
    if (*i == 1) {
      v.push_back(5);
    }
  }
}

带矢量输出: 1 0 3 4 0 0 4113 0 858851888 943206709 2617 。 。 1 2 3 4 五 5

#include <list>
#include <iostream>

using namespace std;

int main() {
  list<int> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);
  v.push_back(4);
  for (list<int>::iterator i = v.begin();
       i != v.end(); i++) {
    cout << *i << endl;
    if (*i == 1) {
      v.push_back(5);
    }
  }
}

带列表的输出: 1 2 3 4 5

2 个答案:

答案 0 :(得分:6)

循环中的一行:

v.push_back(5);

可能使迭代器i无效(在需要重新分配的情况下),因此从那时起++i是未定义的行为。

解决这个问题的一种可能性是首先保留向量,这样就不会发生重新分配:

  vector<int> v;
  v.reserve(5); // reserve enough to keep all the pushed items
  v.push_back(1);
  ...

答案 1 :(得分:1)

您缺少的概念是&#34;迭代器失效&#34;。 std::vector只是一个容量有限的动态数组。添加新元素会导致数组大小大于容量时,需要重新分配,这会使向量的所有迭代器无效。这是在标准草案中的#34; 23.3.7.5向量修饰符&#34;部分中定义的,其中涉及insertpush_back

  

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

另一方面,

std::list是一个双向链表。因此,不需要对列表中已有的任何元素进行重新分配,只有std::list<T>::end()迭代器无效。但是,由于您在循环条件中调用该方法,因此您的代码恰好可以正常工作。