Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.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_Language Lawyer_Undefined Behavior - Fatal编程技术网

C++ 使用指向保留向量元素的指针合法吗?

C++ 使用指向保留向量元素的指针合法吗?,c++,pointers,vector,language-lawyer,undefined-behavior,C++,Pointers,Vector,Language Lawyer,Undefined Behavior,我很好奇这类事情是否合法: std::vector<some_class_type> vec; vec.reserve(10); some_class_type* ptr = vec.data() + 3; // that object doesn't exist yet std::向量向量向量机; 车辆储备(10); 某些类类型*ptr=vec.data()+3;//那个物体还不存在 请注意,我没有尝试访问指向的值 这是标准中关于data()的内容,但我不确定它是否相关: 返回

我很好奇这类事情是否合法:

std::vector<some_class_type> vec;
vec.reserve(10);
some_class_type* ptr = vec.data() + 3; // that object doesn't exist yet
std::向量向量向量机;
车辆储备(10);
某些类类型*ptr=vec.data()+3;//那个物体还不存在
请注意,我没有尝试访问指向的值

这是标准中关于
data()
的内容,但我不确定它是否相关:

返回:
[data(),data()+size())
为有效值的指针 范围。对于非空向量,
data()==&front()


在STL的大多数实现中,空向量的
保留
将触发重新分配,并确保指向它的数据被拥有/管理

数据的位置(由
data()
返回的指针值)调整向量大小时可能会更改。持有指针本身当然是合法的,在未初始化时取消对它的引用以进行读取当然是未定义的,并且只有在您可以保证向量没有调整大小并且分配的范围仍然在同一位置时,在初始化后取消对它的引用才是合法的


递增指向已被
malloc
'd分配的数据的指针是可以的。在本例中,您可以执行指针算法来保存指向已知已由
std::vector
分配的数据的指针。无论指针指向的元素是否已初始化,调整大小操作都有问题,因为它可能会导致l查找您指向的内存。

肯定:无法假定您的指针有效。以下是它有效的证明:

标准规定了容量(23.3.6.3)
reserve()
具有以下效果:

一种指令,通知一个计划大小变化的向量,因此 它可以相应地管理存储分配。之后 reserve(),capacity()大于或等于reserve的参数 如果发生重新分配;且等于先前的容量值() 否则,当且仅当 当前容量小于reserve()的参数

因此,标准保证,如果分配了一些东西,但没有足够的容量,此时必须进行重新分配,但仅此而已


这种措辞允许实现以其他方式管理空向量。例如,我们完全可以想象,一个实现可能不为刚创建的空向量分配内存,而只在添加第一个元素时分配所需的容量(“延迟分配”策略)

在这种情况下,您的示例将导致指向无效地址的指针

重要编辑:
有些人可能会说“如果且仅当”子句将确保必须在示例中进行分配,因为新容量将大于初始容量。但是,该标准未对向量的初始容量提出任何声明。该实现将使用面向集团的延迟分配策略(即,按最小组管理容量,如10项)将符合标准,并导致您的示例指向上面解释的无效地址。

我认为指针本身的初始化是合法的。取消对它的引用是UB。从我所看到的,您使用
reserve
所做的工作与
malloc
类似,其中分配了内存,但未初始化。To老实说,我并不完全熟悉该标准,但从逻辑上讲,如果这不合法,那么
malloc
也不合法。我想这一切都取决于是否必须在调用
reserve
时分配阵列内存,或者是否可以推迟到第一次访问。如果标准中没有明确要求,我将ppose一些实现可能会推迟分配,这可能至少会推迟到UB。不确定是否会考虑调用
数据
“首先评估”或足够调用分配(如果是这种情况)。@Nard:为了完成起见,这里也有响应--
reserve
malloc
之间的区别是未来的调整大小操作(例如,由向量超过其容量的增长触发)将导致数据重新分配,可能使
ptr
指向的内存区域无效。@EyasSH换句话说,
reserve
不一定调用
malloc
realloc
,标准仅将其定义为一个函数,通知向量大小的计划变化,从而确定其实际值lly是否依赖于实现,对吗?因此,将
reserve
视为
malloc
的谬误在于,调用
reserve
时可能无法分配内存,因此OP所做的肯定是未定义的行为,我想?我看不出指针本身会如何变化但是,指针指向的数据在
调整大小
操作期间可能会更改。@Nard指针在容量更改时随时都可能变为无效,因为底层实现可能使用
realloc
,如果当前内存块无法扩展到位,它可能返回不同的地址。我很确定
data()
返回的指针可以更改。
std::vector
保留移动数据块的权利。这就是向量如何在保持其相邻的同时增长其基础数组。@Nard用于
data()
的指针可以因
resize()而更改
操作。@Nard-数据的位置可以通过调整大小而改变。由
data()
返回的指针是指向数据位置的指针。因此,由
data()
返回的值可以改变。我不会对空向量这样做。而且,该措辞保证内存存在