如何删除自定义节点并使其在函数中为nullptr


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->nextnxtroot->next=nxt之后的一个东西,事实是root->next只是nxt的一个副本,它们具有相同的值,但存储在不同的内存中。换句话说,它们是两个不同的指针,但指向相同的内存,其中存储nodeval==2next==nullptr.因此,不可能通过root删除nxt,func()也发生了同样的错误。

我修改了代码,以显示root->nextnxt之间的相似点和不同点。

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时,您正在破坏proot->next都指向的Node对象。您将p设置为nullptr(这是多余的,因为p之后立即超出范围),但是您将root->next悬空。

要修复func(),使(root->next==nullptr)条件在main()中变为真,您有两个选择:

  1. 去掉p,直接作用于root->next:

    void func(node* root)
    {
    delete root->next;
    root->next = nullptr;
    }
    
  2. 使p成为root->next引用而不是复制:

    void func(node* root)
    {
    node* &p = root->next;
    delete p;
    p = nullptr;
    }
    

但是,func()所做的任何事情都不会影响main()中的nxt变量,因为nxtmain()的局部变量,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
}

最新更新