向量的变化第一指针
Posted
技术标签:
【中文标题】向量的变化第一指针【英文标题】:change of vectors first pointer 【发布时间】:2010-10-25 09:25:16 【问题描述】:当我使用向量存储一些数据时,我通常通过向量的第一个条目的指针来访问这些数据。因为它比 at() 方法快。但是我意识到当我插入一个数据块时,比如一个数组到向量的末尾,第一个条目的指针会改变。这可能与堆栈的东西有关,但是如果我通过 push_back 一次添加一个元素,第一个指针不会改变。那为什么呢?我应该担心使用指针来访问元素吗?
这里有一个示例代码供想要查看的人使用:
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;
【问题讨论】:
Ewewew...在一个地方而不是另一个地方使用vector
有什么意义?
@GMan:当您尝试在代码中使用漂亮的 STL 容器但必须使用其他人的使用 c 样式数组的函数时。在我的经验中太常见了。
@GMan:你的意思是我的回答?谢谢 - 很好。
@beldaz:我的意思是使用new[]
而不是std::vector
的理由为零。您可以获得与 &v[0]
相同的结果。
【参考方案1】:
std::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);
这会拖累性能,因为您反复要求操作系统提供更多内存,并且每次迭代都会导致更大的复制操作。
【讨论】:
好吧,我特别需要在我的应用程序中通过 insert() 方法添加数据,当我保留然后插入时,第一个指针再次发生变化。我应该总是在循环中使用 push_data 吗? @bahadir:插入会导致插入点之后的所有数据都被碰撞。 push_back 是将数据添加到向量的最佳方式,但只有在您想要数据的地方才有帮助。如果您在其他地方插入数据,请考虑 deque 或 list 作为更合适的替代方案。【参考方案2】:当您添加元素时,向量可能会重新分配到堆上更大的内存区域。如果您想要更高的性能,您应该使用[]
而不是at()
,但是您必须确保您的索引在范围内:这通常很容易确保。这是非常糟糕的做法,并且完全没有必要从向量开始指针开始缓存和索引:只需打开优化器并确保您没有使用 STL 的某些调试模式“检查迭代器”模式(如果它有一个,例如 Visual C++),并且性能无论如何都是相同的。
如果您知道向量可以增长到的最大大小,那么您可以使用reserve() 预先确定它的大小。
【讨论】:
嗯,性能差异非常小,但是在开发算法交易应用程序时,您需要所有的武器。【参考方案3】:使用reserve()
防止在插入许多元素之前分配多个内存。
然后获取您的“第一个指针”,如果您正确保留了正确数量的元素,则该指针不应更改。
但是你为什么不使用 begin()
呢? *
和 ->
运营商致力于此,你知道...
【讨论】:
以上是关于向量的变化第一指针的主要内容,如果未能解决你的问题,请参考以下文章