0

0

C++ 析构函数中的虚析构是什么?(如何防止子类内存泄漏)

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-02-15 15:04:07

|

399人浏览过

|

来源于php中文网

原创

基类析构函数必须是虚函数,否则通过基类指针删除派生类对象时仅调用基类析构,导致派生类资源未释放而引发内存或资源泄漏;标准规定此行为为未定义行为。

c++ 析构函数中的虚析构是什么?(如何防止子类内存泄漏)

为什么基类析构函数必须是虚函数

当你用 new 创建一个派生类对象,却通过基类指针删除它(delete base_ptr),如果基类析构函数不是虚函数,C++ 只会调用基类的析构函数,派生类自己的析构逻辑(比如释放 new 出来的成员、关闭文件句柄、解注册回调)根本不会执行——这直接导致内存泄漏或资源泄露。

这不是“可能出问题”,而是标准明确规定的行为:非虚析构 + 多态删除 = 未定义行为(UB),常见表现是程序没报错但内存持续增长,或者崩溃在奇怪的位置。

怎么加虚析构:语法和位置

虚析构函数写法很简单,但必须加在基类里,且通常声明为 virtual ~Base() = default; 或带空实现。注意两点:

  • 派生类析构函数自动继承虚性,无需再写 virtual(写了也不报错,但冗余)
  • 如果基类有虚函数(比如 virtual void draw()),那它本就应该有虚析构;没有虚函数但又打算被继承并多态删除的类,也必须加
  • 纯虚析构函数可以存在,但必须提供定义:virtual ~Base() = 0; 后面得跟 Base::~Base() {}

示例:

立即学习C++免费学习笔记(深入)”;

FlowMuse AI
FlowMuse AI

节点式AI视觉创作引擎

下载
class Base {
public:
    virtual ~Base() = default; // ✅ 关键就这一行
};
<p>class Derived : public Base {
int* data = new int[100];
public:
~Derived() override { delete[] data; } // 自动虚,不用写 virtual
};

不加虚析构的典型错误现场

最容易踩坑的是容器存指针、工厂函数返回基类指针、以及用智能指针但没配对自定义删除器的场景:

  • std::vector<base> vec; vec.push_back(new Derived); ... for (auto p : vec) delete p; → 派生类析构不执行
  • 工厂函数返回 std::unique_ptr<base>,但基类析构非虚 → unique_ptr 析构时仍只调基类
  • 把派生类对象地址赋给 Base* 后,直接 delete —— 即使你确定当前对象是派生类,只要类型是 Base*,编译器就按非虚处理

这些情况不会编译报错,运行时也未必立刻崩,但资源泄漏往往在长期运行或压力测试中才暴露。

虚析构带来的开销和例外

虚析构函数会让类变成多态类型,增加一个虚函数表指针(通常 8 字节),所有对象实例都多占这点空间。但这是必要代价,别为了省几个字节去赌“我永远不会多态删除”。

真正可以不加虚析构的只有两种情况:

  • 类明确设计为不可继承(加 final,如 class Base final { ... };
  • 类纯粹作接口聚合(比如只含 static 成员或类型别名),根本不分配堆内存,也不持有任何需清理的资源

哪怕只是“暂时没写派生类”,只要头文件公开、别人可能继承,就必须加虚析构——C++ 不做假设,只认定义。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

22

2025.11.27

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

22

2025.11.27

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

181

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

114

2025.11.27

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1442

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

362

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2217

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

37

2026.01.19

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

76

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.4万人学习

C 教程
C 教程

共75课时 | 4.7万人学习

C++教程
C++教程

共115课时 | 17.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号