这看起来很简单,但我的朋友和我一起辩论,下面的程序会调用UB。但我认为他是不正确的。 请考虑以下计划:
#include <iostream>
int main()
{
int* p=new int[3]();
int* q=p;
for(int i=0;i<3;i++)
std::cout<<q[i]<<' ';
delete[] q;
std::cout<<'\n';
}
这个节目的行为是否定义明确?如果我写删除[] p; 而不是删除[] q; ,会发生什么?它有效吗?
答案 0 :(得分:5)
是的,该计划定义明确。首先,创建一个分配给新分配的内存的指针。
renderPartial
然后创建指向该内存的另一个指针
int* p=new int[3]();
然后使用该指针将数据分配到该内存中。之后删除指向int* q=p;
的内存,该内存与q
相同,这是可以的。程序返回,一切都很好
p
并不关心您使用的变量。重要的是指针指向的内存是用delete
创建的,而你只在内存上调用一次。
答案 1 :(得分:2)
new[]
运算符返回的指针不是分配内存的开头,而是指向第一个对象(或索引0处的对象)。现在,based on the compiler you're using,运行时系统存储对象的数量n,如果您只知道p
指向的内存位置,则可以在其中检索它。
According to this blog,删除向量反向执行此操作:
当你做&#34;删除[] p&#34;,你说,&#34; p指向一堆 对象,但我不告诉你有多少。&#34;在这种情况下,编译器 需要生成额外的代码来跟踪它需要多少 破坏。这些额外信息保存在一个秘密的地方&#34;当。。。的时候 vector用&#34; new []&#34;。
分配
由于执行int *q = p
实际上指向同一个数组的第0个对象,因此它等同于调用delete[] q
和delete[] p
。
答案 2 :(得分:1)
没有UB。它会工作正常。在这里添加不多。
答案 3 :(得分:1)
运算符delete
只能应用于使用运算符new
分配的内存(即地址)。如果你分配一次你应该释放(检测)一次,不会使用哪个指针(变量存储地址),所以你的代码是有效的。
但是,请记住,在delete[] q
之后,q
和p
都不必使用。最好的方法是两个指针的assigne NULL
。