STL中的矢量push_back?

时间:2016-05-04 01:40:02

标签: c++ vector stl

我找到了一个为STL Vectors

尝试的示例程序
#include <vector>
#include <iostream>

using namespace std;

/* This one may well work with some compilers/OS, and crash with
   others. Who said the STL was safe ?? */

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 2 3 4 5

但是,结果非常奇怪 - 1 0 3 4 0 0 33 0 0 0 0 0 0 0 49 0 1 2 3 4 5 5

我猜,这有一些我缺失的逻辑,因为它们看起来不像垃圾值,因为结果总是相同的。 做push_back之后,迭代器是重置还是什么? 我已经把它读到某个地方,在迭代它时附加一个向量并不是一个好主意。我的问题是为什么?

经过互联网搜索后,

     if (*i == 1) {
       size_t diff = i-v.begin();
       v.push_back(5);
       i = v.begin()+diff;
     }

这将解决问题。

3 个答案:

答案 0 :(得分:3)

您正在修改std::vector,同时循环播放它。致电std::vector::push_back()时,如果其当前size()等于其当前capacity(),则std::vector必须重新分配其内部数据存储以增加其容量,然后才能存储新的价值。该重新分配将使循环iterator无效(end()迭代器始终无效,但您在每次迭代时都重新评估它,因此在这种情况下就可以了。)

要做你正在尝试的事情,要么:

  1. reserve() vector在进入循环之前的容量,以避免重新分配,从而避免使循环iterator失效。

  2. 在每次重新分配后重置迭代器。

  3. 改为使用std::list,因为iterator不会使循环std::list::push_back()失效。

答案 1 :(得分:3)

因为std::vector::push_back可能使所有迭代器无效。

  

如果new size()大于capacity(),那么所有迭代器和引用(包括过去的迭代器)都将失效。

对于您的代码,您可以使用std::vector::reserve来避免重新分配。

  

将容器的容量增加到大于或等于new_cap的值。

int main() {
  vector<int> v;
  v.reserve(5);  // ensure no reallocation until size() == 5
  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);
    }
  }
}

正如你所说,在迭代它时附加一个向量并不是一个好主意。

答案 2 :(得分:1)

现有答案中有一些不错的选择,但是当你知道由于push_back超出容量调整而面临潜在的迭代器失效时,值得一提的是另一个被遗忘的选项:

for (size_t i = 0; i < v.size(); ++i) {
    cout << v[i] << endl;
    if (v[i] == 1)
        v.push_back(5);
}

这是“C风格”,但简单直观。