You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++链表删除持有后继节点地址的节点时析构函数行为及内存相关疑问

解答

1 删除指针p时析构函数的执行逻辑

你给出的Node类析构函数是递归实现:只要当前节点的next指针不为空,就会执行delete next触发下一个节点的析构。
针对你的疑问直接回答:

  • 该场景下执行delete p时,首先触发p指向节点的析构函数,析构函数会检查到p->next不为空,自动递归删除p->next、p->next->next……直到某一个节点的next为NULL才停止。
  • 这个过程确实会遍历p节点之后所有连接的节点,但是不是将节点置空,而是把所有涉及到的节点的资源全部释放,对应内存会被回收。
    这里也是你给出代码的核心错误:你已经把p->next赋值给了q->next,但delete p时会把p->next指向的后续节点全部释放,导致q->next变成野指针,后续执行p = q->next就会触发非法内存访问。

2 析构函数和deallocation的核心区别

你可以把delete操作的执行过程拆解为固定的两步,就能理清两者的关系:

  • 第一步:调用目标对象的析构函数。析构函数的作用是清理对象持有的外部资源,比如你这里Node类的析构负责释放它管理的下一个节点资源,其他场景下可能是关闭文件、释放其他堆内存、断开网络连接等,它本身不会释放当前对象自身占用的内存。
  • 第二步:执行内存释放(也就是deallocation),把当前对象占用的堆内存还给操作系统,这一步才是真正的内存回收操作。
    补充两个常见的区别点:
  • 如果你用free释放对象,只会执行第二步的deallocation,不会调用析构函数,所以类对象的资源清理必须用delete不能用free。
  • 析构函数可以手动调用,但几乎没有场景需要你这么做,手动调用析构函数不会触发内存释放,只有delete操作会同时完成析构+内存释放两个流程。

相关代码

class Node {
    public:
        int data;
        Node * next;
        Node(int data){
            this -> data = data;
            this -> next = NULL;
        }
    
        ~Node() {
            if(next) {
                delete next;
            }
        }
    };
void deleteAlternateNodes(Node *head) {
    //Write your code here
    Node *p =head;
    Node *q =NULL;
   if(p->next == NULL)
   {
       return;
   }
    while(p!=NULL)
    {
        q=p;
        p=p->next;
        q->next = p->next;
        delete p;
        p = q->next;
    }
}

内容的提问来源于stack exchange,提问作者Abhinav 1036

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 00:06:02