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

C++双向链表Link结构体remove()函数原理及内存泄漏疑问

问题背景

我在学习C++,在Bjarne Stroustrup所著《The C++ Programming Language, 4th Edition》的第465、466页接触到struct Link {};相关代码。为方便理解代码执行逻辑,我在原代码基础上添加了打印内存地址的调试输出,完整代码如下(注:原代码第一行缺少#,正确写法应为#include <iostream>):

#include <iostream>
using std::cout;
using std::endl;

struct Link {
    Link* prev;
    Link* next;
    int data;
    Link* insert(int x) {
        prev = new Link{prev, this, x};
        cout << "address of new prev:" << prev << endl;
        cout << "address of new prev->prev:" << prev->prev << endl;
        cout << "address of new prev->next:" << prev->next << endl;
        cout << "prev->data :" << prev->data << endl;
        cout << "address of this:" << this << endl;
        return prev;
    }

    void remove() {
        cout << "\n\nRemoving elements!" << endl;        
        if (prev) {
            cout << "Removing data:" << prev->data << endl;
            cout << "Before prev:" << prev << " " << "prev->next:" << prev->next << endl;
            prev->next = next;
            cout << "After prev:" << prev << " " << "prev->next:" << prev->next << endl;
        }
        if (next) {
            cout << "Removing data:" << next->data << endl;
            next->prev = prev;
            cout << "next:" << next << " " << "next->prev:" << next->prev << endl;
        }
        delete this;
    }

    void print() {
        Link* temp = prev;
        while (temp != nullptr) {
            cout << "temp->data:" << temp->data << endl;
            temp = temp->prev;
        }
    }
};

int main() {
    Link* x {new Link};
    cout << "Address of x:" << x << endl;
    x->prev = nullptr;
    x->next = nullptr;
    cout << "\n\nInserting:2"<< endl;
    x->insert(2);
    cout << "\n\nInserting:4"<< endl;
    x->insert(4);
    cout << "\n\nInserting:5"<< endl;
    x->insert(5);
    x->remove();
    return 0;
}

我在学习过程中无法准确理解remove()函数移除并销毁this指向对象的具体逻辑:根据代码实现,该函数并未遍历销毁整个链表,仅将prev->next赋值为next(当前测试场景下next值为0x0空指针),请问该理解是否正确?如果理解正确,存储数值2、4的节点所占用的内存并未被释放,这种情况是否属于内存泄漏?


解答

你的理解完全正确,逐部分说明如下:

remove()函数的实际逻辑

这个函数的设计目标是从双向链表中摘除并释放当前this指向的单个节点,本身就不负责销毁整条链表,执行流程非常清晰:

  • 若当前节点存在前驱节点(prev不为空):将前驱节点的next指针指向当前节点的后继节点,让前驱直接跨过当前要删除的节点,和后继建立正向连接。你的测试场景里初始创建的x节点next始终是空指针,因此执行完这步后,前面插入的存5、4、2的节点链的尾端next会被设为空。
  • 若当前节点存在后继节点(next不为空):将后继节点的prev指针指向当前节点的前驱节点,补全反向连接。你的测试场景里x->next一直是空,这部分逻辑不会触发。
  • 最后执行delete this,仅释放当前this指向的这一个节点(也就是main里一开始new出来的、没有存有效业务数据的初始x节点),完全不会顺着prev/next指针遍历释放其他节点。

内存泄漏判定

你测试场景下存储2、4、5的三个节点确实没有被释放,属于典型的内存泄漏:
这三个节点都是堆上动态分配的内存,当x节点被delete之后,你没有保存任何指向这三个节点的指针,程序后续既无法访问这部分内存,也没有主动释放的路径,完全符合内存泄漏的定义——动态分配的堆内存未被释放且失去了所有访问入口,造成内存资源浪费。

需要说明的是,原书这段代码只是用来演示双向链表单节点摘除的最基础语法逻辑,并不是生产环境可用的、无内存安全问题的完整链表实现。如果要做到无泄漏,还需要补充链表整体析构时的遍历释放逻辑、节点增删时的指针所有权管理,不能直接照搬这段演示代码使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:57:27