我的问题:
int* x = new int;
cout << x<<"\n";
int* p;
cout << p <<"\n";
p = x;
delete p;
cout << p <<"\n";
Run Code Online (Sandbox Code Playgroud)
我自己写这篇文章是为了理解指针并理解(也迷失)动态new
和delete
.
我的XCode可以编译程序并返回以下结果:
0x100104250
0x0
0x100104250
Run Code Online (Sandbox Code Playgroud)
我知道我只能在动态分配的内存上调用delete.但是,我p
在上面的程序中调用了delete 并编译.
谁有人向我解释这个?我为什么要删除p
?
此外,我发现程序是否更改为以下内容:
int* x = new int;
int* p;
cout << p <<"\n";
delete p;
cout << p <<"\n";
Run Code Online (Sandbox Code Playgroud)
然后我的Xcode再次编译并返回给我:
0x0
0x0
Program ended with exit code: 0
Run Code Online (Sandbox Code Playgroud)
现在,我完全迷失了:(.有人可以解释一下吗?为什么我可以删除,p
因为它没有任何关系x
?
由于Xcode编译成功,我认为上述两个程序对于计算机是正确的.但是,我认为这又是"只对动态分配的内存进行调用删除"的陈述.或者可能,我没有完全理解什么是指针以及什么是动态分配的内存.我在网上搜索时找到了这篇文章.但我不认为这就像我的情况.
请帮帮我.
我想再问一个问题.代码在这里是关于二叉搜索树.从第28行到第32行,它涉及删除一个孩子的节点.我把这部分代码放在这里,万一网页链接不起作用.
else if(root-> left == NULL){struct Node*temp = root; root = root-> right; 删除临时; }
正是这些代码引导我问上面关于指针的问题.按照这篇文章给出的答案.以下列方式理解代码是否正确?
我不能先将root的父节点链接到root的右子节点.然后删除根节点,因为根节点下的子树也将被删除.所以我必须创建一个临时指针,指向由root指向的内存槽.然后我将root的父节点链接到root的右子节点.现在,我可以安全地删除"root"指向的内存插槽(即temp,因为它们都指向同一个内存).通过这种方式,我释放内存并保持父和子之间的链接.此外,temp仍然存在,仍然指向"那个"内存插槽.我应该在删除后将其设置为NULL吗?
再次感谢大家.
腰封
是的,您只能调用delete
通过分配的内存new
。请注意,重要的是内存的地址(指针的值),而不是存储指针的变量。所以,你的第一个代码:
int* x = new int; //(A)
cout << x<<"\n";
int* p;
cout << p <<"\n";
p = x; //(B)
delete p; //(C)
cout << p <<"\n"; //(D)
Run Code Online (Sandbox Code Playgroud)
0x100104250
第 (A) 行在某个地址(在示例输出中)动态分配内存,并将该地址存储在变量中x
。内存是通过分配的new
,这意味着delete
最终必须在地址上调用0x100104250
。
第 (B) 行将地址0x100104250
(指针 的值x
)分配给指针p
。然后,行 (C) 调用delete p
,这意味着“释放 指向的内存p
”。这意味着它调用delete
了地址0x100104250
,一切都很好。地址处的内存0x100104250
是通过 分配的new
,因此未通过 正确分配delete
。您使用不同的变量来存储值的事实没有任何作用。
第 (D) 行仅打印出指针的值。delete
作用于指针指向的内存,而不是指针本身。指针的值保持不变 - 它仍然指向相同的内存,只是不再分配该内存。
第二个示例有所不同 - 您在未初始化任何内容delete p
时调用。p
它指向一块随机的内存,因此调用delete
它当然是非法的(从技术上讲,它具有“未定义的行为”,并且很可能会崩溃)。
看来在您的特定示例中,您正在运行调试版本,并且如果您自己不初始化局部变量,则编译器会“帮助”将局部变量初始化为 0。因此,它实际上会导致您的第二个示例不会崩溃,因为调用delete
空指针是有效的(并且不执行任何操作)。但该程序实际上有一个错误,因为局部变量通常不会隐式初始化。