c++ - vector 第一个指针的变化

标签 c++ pointers vector insert

当我使用 vector 存储一些数据时,我通常通过 vector 第一个条目的指针访问这些数据。因为它比 at() 方法更快。但是我意识到当我插入一个数据 block 时,比如一个数组到 vector 的末尾,第一个条目的指针会发生变化。这可能与堆叠的东西有关,但是如果我通过 push_back 一次向数组添加一个元素,第一个指针不会改变。那是为什么呢?我应该担心使用指针访问元素吗?

这里是一个示例代码,供那些想要 checkout 的人使用:

int arrayLen = 500000;
 vector<int> vint = vector<int>(2000,0);
 int * firstEntry = &vint[0];

 int * iarray = new int[arrayLen];
 for(int i = 0; i< arrayLen; i++)
 {
  iarray[i] = i;
 }
 vint.insert(vint.end(),iarray,iarray+arrayLen);
 cout << firstEntry << "," << &vint[0] << endl; // They ar not equal;

         // reset the vector
 vint.clear();
 vint.resize(2000,0);
 firstEntry = &vint[0];

 for(int i = 0; i< arrayLen; i++)
 {
  vint.push_back(iarray[i]);
  if(firstEntry != &vint[0])
   cout << firstEntry << "," << &vint[0] <<","<< i << endl;
 }// nothing  is written

 cout << firstEntry << "," << &vint[0] << endl; // now they are equal;

最佳答案

std::vector 可以动态调整大小。它这样做的方式是保留比需要更多的空间。一旦达到保留容量,就需要保留更大的数据 block (取决于实现,但新 block 的容量通常是之前大小的两倍)。然后将数据复制到新位置,这就是第一个元素的地址发生变化的原因。

只要您不向 vector 中添加更多数据,就不必担心指向 vector 中数据的指针失效。您可以通过检查 vint.capacity()==vint.size() 来预测进一步的 push_back() 何时会触发调整大小。您还可以通过 &vint[0](或 &vint.at() 获取范围检查)始终使用最新指针而不是复制它来避免使用无效指针。

如果您知道要插入许多新项目,则可以通过使用 reserve() 预分配空间来确保您有足够的容量(如果当前容量小于请求的容量)。但请注意,您不想零碎地做这件事 - 例如

vint.reserve(vint.size() + 2000);
for(int i=0; i<2000; ++i) {
    vint.push_back(i);
}

会很好,但是

for(int i=0; i<2000; ++i) {
    vint.reserve(vint.size() + 1);
    vint.push_back(i);
}

这会拖累性能,因为您反复要求操作系统提供更多内存,并且每次迭代都会引发越来越大的复制操作。

关于c++ - vector 第一个指针的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4013261/

相关文章:

c++ - 正则表达式匹配需要永远

c++ - 为什么此时无法引用智能指针auto_ptr?

C++:根据模板参数设置指针的常量性

C - fscanf 未从文本文件中正确读取数字

c++ - C 和 C++ 的数组大小声明差异

c++ - 在 makefile 的子目录中链接对象构建

javascript - JS - 将二维向量变成曲线?

c++ - 在标准 C++ 中创建动态位​​集?

c++ - 我怎样才能 `unuse` 一个类?

c++ - 对每个元素都是一对的 vector 元素进行排序