C++中析构函数不设为virtual导致内存泄漏示例

一、问题示例

cpp 复制代码
#include <iostream>
using namespace std;

class Base {
public:
    Base() { cout << "Base constructor\n"; }
    ~Base() { cout << "Base destructor\n"; } // 不是 virtual
};

class Derived : public Base {
public:
    Derived() { cout << "Derived constructor\n"; }
    ~Derived() { cout << "Derived destructor\n"; }
};

int main() {
    Base* ptr = new Derived();  // 用 Base 指针指向 Derived 对象
    delete ptr;                 // 只调用 Base 的析构函数
    return 0;
}

二、输出结果


注意:没有调用 Derived 的析构函数

三、问题解释

为什么会这样?

  • Base 的析构函数不是 virtual;

  • 当你执行 delete ptr,编译器只看 ptr 的静态类型(即 Base*),它就只调用 ~Base();

  • 因此,不会调用 Derived 的析构函数,可能会导致:

    • Derived 析构中释放的资源没有释放(内存泄漏);
    • 或者 Derived 析构中有清理逻辑没执行(行为错误);

四、修复方法

将 Base 的析构函数设为 virtual:

cpp 复制代码
class Base {
public:
    virtual ~Base() { cout << "Base destructor\n"; }  // virtual 析构
};

正确输出:


五、图示原理(简化)

如果你用 virtual :

复制代码
Base vtable:
+----------------+
|  &Base::~Base  |  ← 原始虚函数地址
+----------------+

Derived vtable:
+--------------------+
| &Derived::~Derived | ← 覆盖虚析构函数
+--------------------+

delete ptr 会通过 vtable 跳转到 Derived::~Derived → 再调用 Base::~Base

六、总结

是否 virtual delete 派生类指针时行为 是否内存泄漏
否 只调用基类析构函数 有可能
是 调用派生 → 再基类析构 安全

七、经验建议

只要类中有虚函数(即打算支持多态)或你"可能"通过基类指针删除派生类对象,就应该将析构函数声明为 virtual。

最好这样写:

cpp 复制代码
class Base {
public:
    virtual ~Base() = default;
};
相关推荐
hunteritself1 分钟前
AI 挖出 PHP「致命漏洞」!欧洲政府连夜关站,日本首相紧急喊话
开发语言·人工智能·php
努力实干16 分钟前
Qt/C++ 模块化设计与工程组织
开发语言·c++·qt
Rabitebla22 分钟前
【Linux底层原理】 工具篇(二):Vim 编辑器基础操作与简单配置
linux·c++·编辑器·vim
阿里嘎多学长24 分钟前
2026-10-23 GitHub 热点项目精选
开发语言·程序员·github·代码托管
Lhan.zzZ40 分钟前
Qt:动态库模块框架设计
开发语言·c++·qt
quantdash_cc1 小时前
如何从多只股票的历史行情构建收益率矩阵?Python 与 QuantDash 实战教程
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
wuminyu1 小时前
JVM规范学习总结-JVM规范基本概念
java·linux·c语言·jvm·c++
Demon--hx2 小时前
jsoncpp 核心概念梳理:命名空间、Value 容器与格式化输出
c++
不是万能的豆学长5 小时前
filetidy 文件整理助手:一键归类 + 规范重命名(Python 零依赖单文件工具)
大数据·开发语言·python·技术美术
懂点Tech9 小时前
ctfshow MISC入门图片篇(信息附加):misc41解题思路
开发语言·python