C++中的析构函数为什么要写成虚函数?(防止基类指针释放时的内存泄漏)
发布时间 - 2026-01-09 00:00:00 点击率:次基类析构函数不加 virtual 会导致资源泄漏,因为用基类指针 delete 派生类对象时仅调用基类析构,跳过派生类析构逻辑,使堆内存、文件句柄等无法释放;只要存在多态删除可能(如基类被继承或用于智能指针),就必须声明为 virtual,否则引发隐蔽泄漏。
为什么基类析构函数不加 virtual 会导致资源泄漏
当用基类指针指向派生类对象,并通过该指针 delete 时,若基类析构函数不是虚函数,C++ 只会调用基类的析构函数,**完全跳过派生类的析构逻辑**。这意味着派生类中申请的堆内存、打开的文件句柄、持有的锁等资源无法被释放。
典型错误现象:
Base* p = new Derived(); delete p; // 只调用 ~Base(),~Derived() 被静默忽略
- 派生类中
new出来的内存不会被delete -
std::ofstream或FILE*不会关闭,可能丢失数据 - 自定义资源管理(如引用计数、GPU buffer)彻底泄露
什么情况下必须把析构函数声明为 virtual
只要存在「多态删除」的可能,就必须加 virtual。核心判断依据不是“有没有继承”,而是“会不会用基类指针/引用来管理派生类对象的生命周期”。
- 基类设计初衷是被继承(如接口类、抽象基类)→ 必须加
virtual - 基类有至少一个
virtual函数(除析构外)→ 析构也应为virtual,否则行为不一致 - 基类被用于容器或智能指针(如
std::vector<:unique_ptr>>)→ 必须加virtual - 基类仅作工具类、无子类、不通过指针销毁 → 可不加,但加了也没坏处
加 virtual 有什么代价?
虚析构函数会让类变成多态类型,从而引入虚函数表指针(vptr),每个对象增加一个指针大小的开销(通常 8 字节)。但这只是**对象实例的内存开销**,不影响性能热点。
- 构造/析构本身开销极小:虚调用只在
delete时发生一次,且现代编译器常能内联 - 不会影响非虚成员函数调用速度
- 唯一真实代价是:强制要求所有派生类析构函数也隐式为
virtual(符合预期)
反例:有人为省 8 字节而省略 virtual,结果导致难以追踪的资源泄漏——这远比内存开销严重得多。
正确写法与常见误区
标准写法是声明为 virtual,且推荐显式加上 = default 或空实现,避免意外生成非虚版本。
class Base {
public:
virtual ~Base() = default; // ✅ 推荐:简洁、明确、无副作用
// 或
// virtual ~Base(
) {} // ✅ 也可,但不如 = default 清晰
};- ❌ 错误:只在派生类写
virtual ~Derived(),基类没写 → 多态删除仍只调用基类析构 - ❌ 错误:基类析构写成
virtual void cleanup()而非析构函数 → 无法自动触发,必须手动调用 - ✅ 正确:哪怕基类没有资源要清理,也要写
virtual ~Base() = default,为子类留出安全出口
最易被忽略的一点:即使你当前所有派生类都只用栈对象(Derived d;),只要未来有人把它放进 std::unique_ptr 或传给某个通用销毁函数,没加 virtual 的基类析构就会立刻变成隐患。
# 字节
# 工具
# 栈
# c++
# stream
# 热点
# 为什么
# 多态
# 成员函数
# 子类
# 析构函数
# void
# 指针
# 继承
# 虚函数
# 接口
# ofstream
# 堆
# delete
# 对象
# default
# 派生类
# 不加
# 句柄
# 只在
# 跳过
# 类中
# 有什么
# 就会
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何用VPS主机快速搭建个人网站?
大型企业网站制作流程,做网站需要注册公司吗?
Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】
Android自定义listview布局实现上拉加载下拉刷新功能
Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层
头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?
如何为不同团队 ID 动态生成多个非值班状态按钮
瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口
Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】
Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】
如何在橙子建站中快速调整背景颜色?
zabbix利用python脚本发送报警邮件的方法
,在苏州找工作,上哪个网站比较好?
Laravel如何记录日志_Laravel Logging系统配置与自定义日志通道
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
如何挑选最适合建站的高性能VPS主机?
如何快速搭建高效WAP手机网站吸引移动用户?
高端企业智能建站程序:SEO优化与响应式模板定制开发
如何用AI帮你把自己的生活经历写成一个有趣的故事?
香港服务器如何优化才能显著提升网站加载速度?
活动邀请函制作网站有哪些,活动邀请函文案?
如何在云虚拟主机上快速搭建个人网站?
今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】
Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】
微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】
Laravel队列任务超时怎么办_Laravel Queue Timeout设置详解
香港服务器网站推广:SEO优化与外贸独立站搭建策略
Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
Android自定义控件实现温度旋转按钮效果
Linux系统命令中screen命令详解
Java解压缩zip - 解压缩多个文件或文件夹实例
PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)
公司门户网站制作流程,华为官网怎么做?
清除minerd进程的简单方法
如何快速重置建站主机并恢复默认配置?
如何用虚拟主机快速搭建网站?详细步骤解析
使用spring连接及操作mongodb3.0实例
PHP 实现电台节目表的智能时间匹配与今日/明日轮播逻辑
浅述节点的创建及常见功能的实现
Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】
浅谈Javascript中的Label语句
手机网站制作与建设方案,手机网站如何建设?
php json中文编码为null的解决办法
网站优化排名时,需要考虑哪些问题呢?
html5源代码发行怎么设置权限_访问权限控制方法与实践【指南】
如何快速搭建高效香港服务器网站?
文字头像制作网站推荐软件,醒图能自动配文字吗?
历史网站制作软件,华为如何找回被删除的网站?
Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程


) {} // ✅ 也可,但不如 = default 清晰
};