矢量指针位置保证?

时间:2012-01-05 04:49:33

标签: c++ pointers vector

假设我有一个整数向量,

std::vector<int> numbers;

填充了一堆值,然后我说这样做(43处存在一个条目)

int *oneNumber = &numbers[43];

oneNumber是否保证始终指向索引43处的int,即使我说我将数字调整为number.resize(46)之类的内容?

我不是100%确定这里的预期行为是什么,我知道矢量保证是连续的但不确定这种连续性是否也意味着矢量中的所有指数在其整个生命周期中都将保持在同一位置。 / p>

7 个答案:

答案 0 :(得分:7)

  

oneNumber是否保证始终指向索引43处的int

是的,标准保证了这一点。

  

即使说我将数字调整为像numbers.resize(46)这样的数字?

没有。一旦为向量调整大小,添加或删除任何内容,它的所有地址和迭代器都将失效。这是因为可能需要使用新的内存位置重新分配向量。

答案 1 :(得分:4)

你的偏执是正确的。调整std::vector的大小可能会导致其内存位置发生变化。这意味着您的oneNumber现在指向已释放的旧内存位置,因此访问它是未定义的行为。

答案 2 :(得分:4)

std::vector元素的指针,引用和迭代器只要您只追加std::vector {{1}的大小,就可以保留。在获得指针,引用或迭代器时,它不会超过其std::vector。一旦调整大小超出capacity()所有指针,引用和此capacity()的迭代器就会失效。请注意,当插入std::vector的末尾以外的其他位置时,事情也会失效。

如果您希望保留对象,并且只在结尾或开头插入新元素,则可以使用std::vector。当您插入std::deque的中间或从中间删除或删除引用的对象时,指针和std::deque中元素的引用只会失效。请注意,每次将元素插入std::deque或从中删除任何元素时,std::deque中元素的迭代器都会失效。

答案 3 :(得分:4)

正如所有其他人所说,当你在向量上调用.resize()时,你的指针会变得无效,因为(旧数组)可能被完全释放,并且可能会重新分配一个全新的指针并复制你的数据进入它。

对此的一种解决方法是 不将指针 存储到STL向量中。相反,存储整数索引

所以在你的例子中,

std::vector<int> numbers;
int *oneNumber = &numbers[43]; // no. pointers invalidated after .resize or possibly .push_back.
int oneNumberIndex = 43 ;      // yes. indices remain valid through .resize/.push_back

答案 4 :(得分:2)

否 - 向量可以在增长时重新分配。通常一旦矢量的大小翻倍。

来自C ++ 11标准

1 Remarks: Causes reallocation if the new size is greater than the old capacity. If no
reallocation happens, all the iterators and references before the insertion point
remain valid. If an exception is thrown other than by the copy constructor, move 
constructor, assignment operator, or move assignment operator of T or by any 
InputIterator operation there are no effects. If an exception is thrown by the move 
constructor of a non-CopyInsertable T, the effects are unspecified.

答案 5 :(得分:2)

当使用向量的resize()或reserve()函数来增加向量的容量时,可能需要为数组后备重新分配内存。如果它重新分配,新内存将不会位于同一地址,因此存储在oneNumber中的地址将不再指向正确的位置。

同样,这取决于当前用于存储的向量的元素数量和请求的大小。根据具体情况,矢量可能无需重新分配即可调整大小,但您绝对不能认为情况会如此。

答案 6 :(得分:2)

更改了向量的容量后,数据被复制到另一个内存块,原始数据被删除。