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
相关产品推荐
相关产品推荐

