【发布时间】:2015-02-05 20:41:30
【问题描述】:
我的问题:
int* x = new int;
cout << x<<"\n";
int* p;
cout << p <<"\n";
p = x;
delete p;
cout << p <<"\n";
我自己写这个纯粹是为了理解指针并理解(也迷失在)动态new和delete。
我的 XCode 可以编译程序并返回以下结果:
0x100104250
0x0
0x100104250
我知道我只能在动态分配的内存上调用 delete。
但是,我在上面的程序中对p 调用了delete,它编译了。
谁能给我解释一下?
为什么我可以删除p?
另外,我发现如果程序改成下面这样:
int* x = new int;
int* p;
cout << p <<"\n";
delete p;
cout << p <<"\n";
然后我的 Xcode 再次编译并返回我:
0x0
0x0
Program ended with exit code: 0
现在,我完全迷路了:(。
谁能给我解释一下?
为什么我可以删除p,因为它与x 无关?
由于 Xcode 编译成功,我假设以上两个程序在计算机上是正确的。 但是,我认为这又是“仅在动态分配的内存上调用删除”的声明。 或者可能,我没有完全理解什么是指针,什么是动态分配的内存。 我在网上搜索时发现了这个post。 但我不认为它像我的情况。
请帮帮我。
我想再问一个问题。关于二叉搜索树的代码是here。 从第 28 行到第 32 行,它处理删除具有一个子节点的节点。 我把这部分代码放在这里,以防网页链接失效。
else if(root->left == NULL) { 结构节点 *temp = root; 根=根->对; 删除温度; }
正是这些代码引导我提出上述关于指针的问题。 按照这篇文章给出的答案。 下面这样理解代码是否正确?
我不能首先将根的父节点链接到根的右子节点。 然后删除根节点,因为根节点下面的子树也会被删除。 所以我必须创建一个临时指针,指向内存槽,也就是root所指向的内存槽。 然后我将根的父节点链接到根的右子节点。 现在,我可以安全地删除“root”指向的内存插槽(即 temp,因为它们都指向同一个内存)。 这样,我释放了内存,也保持了父母和孩子之间的联系。 此外,温度仍然存在并且仍然指向“那个”内存插槽。 删除后是否应该设置为NULL?
再次提前感谢大家。
耀峰
【问题讨论】:
-
您很“幸运”,在您的第二个代码示例中
p是0。由于它是未初始化的,它可以有任何值。因为它是0(又名NULL),所以调用delete是有效的(这有助于避免对NULL进行一百万次检查,特别是在处理分配失败的错误情况时,并且您想要清理其余的分配——如果所有的指针都先初始化为NULL,那么你可以只用delete所有的东西,不用担心哪个分配失败)。 -
只是一个建议,你总是应该初始化你的指针变量,比如 int *p = 0;或 int *p = NULL;那是因为在调试版本中,这将为您完成。但在发布版本中,它不会完成。这可以为您节省大量调试时间。
-
@user743414 除非您要维护旧代码,否则您应该使用 C++11,因此应该使用
int *p = nullptr;。 (这部分)C++11 多年来一直被所有主要编译器支持。 -
@Angew 好吧。我不知道。 :) 看来我学到了新东西。
-
您可能想看看stackoverflow.com/a/6445794/1382251。虽然是指局部变量的生命周期,但概念是一样的。