C++ 矢量指针位置保证?
假设我有一个整数向量C++ 矢量指针位置保证?,c++,pointers,vector,C++,Pointers,Vector,假设我有一个整数向量 std::vector<int> numbers; 即使我将数字调整为类似数字的大小,oneNumber是否保证始终指向索引43处的整数。调整大小(46) 我不是100%确定这里的预期行为是什么,我知道向量保证是连续的,但不确定这种连续性是否也意味着向量中的所有索引在其整个生命周期中将保持在同一位置。否-向量在增长时可以重新分配。通常,一旦向量的大小加倍 来自C++11标准 1 Remarks: Causes reallocation if the new s
std::vector<int> numbers;
即使我将数字调整为类似数字的大小,oneNumber是否保证始终指向索引43处的整数。调整大小(46)
我不是100%确定这里的预期行为是什么,我知道向量保证是连续的,但不确定这种连续性是否也意味着向量中的所有索引在其整个生命周期中将保持在同一位置。否-向量在增长时可以重新分配。通常,一旦向量的大小加倍 来自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.
是否保证oneNumber始终指向索引43处的int
是的,这是由标准保证的
即使说我把数字调整为类似数字的大小。调整大小(46)
不可以。一旦您调整、添加或删除向量中的任何内容,它的所有地址和迭代器都将无效。这是因为向量可能需要重新分配新的内存位置。你的偏执是正确的。调整std::vector的大小会导致其内存位置发生变化。这意味着您的
oneNumber
现在指向已释放的旧内存位置,因此访问它是未定义的行为。当您使用向量的resize()或reserve()函数来增加向量的容量时,它可能需要为阵列备份重新分配内存。如果重新分配,新内存将不会位于同一地址,因此存储在oneNumber中的地址将不再指向正确的位置
同样,这取决于向量当前用于存储的元素数量和请求的大小。根据具体情况,向量可能能够在不重新分配的情况下调整大小,但您绝对不应假设情况会如此。指针、引用、,只要只向
std::vector
追加std::vector
并且std::vector
的大小在获取指针、引用或迭代器时不会超出其容量()
,则std::vector
元素的迭代器就可以保证保持不变。一旦它的大小超出capacity()
的范围,指向该std::vector
的所有指针、引用和迭代器都将失效。请注意,在插入std::vector
末尾以外的其他位置时,也会使内容无效
如果希望对象保持不变,并且只在末尾或开头插入新元素,可以使用
std::deque
。只有在插入到std::deque
中间或从中间移除或移除被引用对象时,std::deque
中元素的指针和引用才会失效。请注意,每次将元素插入std::deque
或从中删除任何元素时,std::deque
中元素的迭代器都将失效。一旦更改向量的容量,数据将复制到另一个内存块,原始数据将被删除。正如所有其他人所说,在向量上调用.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
std::向量数;
int*oneNumber=&numbers[43];//否。指针在。调整大小或可能。推回后无效。
int-oneNumberIndex=43;//对索引通过.resize/.push_返回保持有效
如果使用std::list
,该怎么办?如果您只使用list.push_back()
调用来添加项目,这会避免地址无效的问题吗?(而且你没有删除oneNumber
指向的项目?@bobobo这是一个好问题。我不确定标准是怎么说的,但我看不出在std::list
中添加/删除会使任何指针无效的原因。(被删除的元素除外)找到了我当前正在使用的对象。因此,我总是担心创建值类型的向量,因为我不可避免地需要指向向量中对象的指针。因此,我保存了一个引用,如int*ref=&numbers[43]
。稍后,将两个推回到数字中s,然后砰!错误:ref
无效,因为numbers
已完全重新分配并保存在完全不同的内存空间中。@bobobobo非常正确。但对于在创建时已知元素数量的情况(不,我不能使用std::array
,因为我emplace
-通过循环构造值),reserve
保证向量中的所有指针/迭代器都将保持有效,只要它的大小不超过其当前容量(这可能会强制重新分配,从而移动包含值的地址)。这帮我省了好几次钱,但每次我都忘了保留
,然后搔搔头一段时间,直到我记起。:D
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