class node
{
public:
node* next;
int val;
};
void func(node* root)
{
node* p=root->next;
delete p;
p=nullptr;
}
int main()
{
node* root=new node();
node* nxt=new node();
root->val=1;root->next=nxt;
nxt->val=2;nxt->next=nullptr;
func(root);
cout<<(nxt==nullptr)<<endl;//false
cout<<(root->next==nullptr)<<endl;//false
}
我如何修改func()
,让最后两行输出1?
func()
"中只能通过"root
"删除"nxt
"。编辑:
起初,我认为root->next
和nxt
是root->next=nxt
之后的一个东西,事实是root->next
只是nxt
的一个副本,它们具有相同的值,但存储在不同的内存中。换句话说,它们是两个不同的指针,但指向相同的内存,其中存储node
与val==2
和next==nullptr
.因此,不可能通过root
删除nxt
,func()
也发生了同样的错误。
我修改了代码,以显示root->next
和nxt
之间的相似点和不同点。
int main()
{
node* root=new node();
node* nxt=new node();
root->val=1;root->next=nxt;
nxt->val=2;nxt->next=nullptr;
//point to same memory
cout<<(root->next)<<endl;
cout<<(nxt)<<endl;
cout<<"---------"<<endl;
//stored in different memory
cout<<&(root->next)<<endl;
cout<<&nxt<<endl;
}
得到如下输出:
0x7219b0
0x7219b0
---------
0x7219a0
0x61ff08
更重要的是,我发现root->next
减去&(root->next)
总是0x10
。在我看来,第一个值是具有val==2
的节点存储的地方,第二个值是具有val==1
的节点中的内存。我猜这是因为两个节点被分配几乎相同的时间,所以操作系统将它们分配在一个连续的内存段中。
希望对其他初学者有所帮助。
在func()
中,p
是它自己唯一的变量。在您的示例中,它保存root->next
中保存的地址的副本。因此,无论您对p
本身做什么,都不会以任何方式影响root->next
。然而,当您调用delete p
时,您正在破坏p
和root->next
都指向的Node
对象。您将p
设置为nullptr
(这是多余的,因为p
之后立即超出范围),但是您将root->next
悬空。
要修复func()
,使(root->next==nullptr)
条件在main()
中变为真,您有两个选择:
-
去掉
p
,直接作用于root->next
:void func(node* root) { delete root->next; root->next = nullptr; }
-
使
p
成为root->next
的引用而不是复制:void func(node* root) { node* &p = root->next; delete p; p = nullptr; }
但是,func()
所做的任何事情都不会影响main()
中的nxt
变量,因为nxt
是main()
的局部变量,func()
没有nxt
存在的概念。这就是为什么(nxt==nullptr)
条件在您的示例中永远不会变为真。事实上,nxt
变量根本不需要存在,例如:
class node
{
public:
int val;
node* next = nullptr;
};
void func(node* root)
{
node* &p = root->next;
delete p;
p = nullptr;
}
int main()
{
node* root = new node{1};
root->next = new node{2};
func(root);
cout << (root->next == nullptr) << endl; // true
}