Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 矢量指针位置保证?_C++_Pointers_Vector - Fatal编程技术网

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