C++中的虚析构函数有什么用?(防止内存泄漏)

虚析构函数确保通过基类指针删除派生类对象时能正确调用派生类析构函数;否则仅调用基类析构,导致派生类资源未释放,引发资源泄漏。

虚析构函数主要不是为了“防止内存泄漏”,而是为了**确保通过基类指针删除派生类对象时,能正确调用派生类的析构函数**。如果没设为虚函数,只会调用基类析构函数,派生类中需要清理的资源(比如动态分配的内存、文件句柄、网络连接等)就可能没被释放——这确实可能间接导致内存泄漏或其他资源泄漏,但根本问题是**析构行为不完整**。

为什么基类析构函数要声明为 virtual?

当用 基类指针指向派生类对象,并用 delete 删除时,C++ 默认只调用该指针静态类型(即基类)的析构函数,不会自动查找并调用实际对象的派生类析构函数。

加上 virtual 后,析构函数就支持动态绑定,运行时能按对象真实类型逐级调用:派生类析构 → 基类析构(自动调用基类部分),保证所有层级的清理逻辑都执行。

不加 virtual 会出什么问题?

看这个典型例子:

class Base {
public:
    ~Base() { cout << "Base dtor\n"; }
};
class Derived : public Base {
    int* p = new int[100];
public:
    ~Derived() { delete[] p; cout << "Derived dtor\n"; }
};

Base* ptr = new Derived(); delete ptr; // 只输出 "Base dtor"!p 没被 delete,内存泄漏发生

这里 Derived 的析构函数根本没执行,new 出的数组一直没释放——这才是内存泄漏的直接原因。

什么时候必须写虚析构函数?

  • 只要一个类设计为**多态基类**(即有 virtual 成员函数,且预期被继承、用基类指针管理派生类对象),它的析构函数就应该声明为 virtual
  • 即使析构函数函数体为空,也要写 virtual ~Base() = default;virtual ~Base() {}
  • 如果类明确不作为基类使用(比如 final 类、或根本不打算用父类指针管理子对象),就不需要虚析构

补充说明

虚析构函数本身不增加内存开销(和其它虚函数一样,只共用一个虚函数表指针);它也不影响栈上对象的析构行为(栈对象总是静态确定类型,自动调用完整析构链)。关键只在 new + delete + 多态指针这种组合场景下起作用。

基本上就这些。不是“防泄漏”的银弹,而是多态资源管理的必要约定。