指针和动态内存分配

Bem*_*i77 5 c++ pointers

我的问题:

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)

我自己写这篇文章是为了理解指针并理解(也迷失)动态newdelete.

我的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吗?

再次感谢大家.

腰封

Rei*_*ica 2

是的,您只能调用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空指针是有效的(并且不执行任何操作)。但该程序实际上有一个错误,因为局部变量通常不会隐式初始化。