0

0

C++怎么写析构函数 C++中RAII管理内存的最佳写法【规范】

尼克

尼克

发布时间:2026-03-15 18:05:20

|

998人浏览过

|

来源于php中文网

原创

析构函数必须是public、noexcept、无参数;否则编译报错或行为未定义,且禁止抛异常,否则导致std::terminate。

c++怎么写析构函数 c++中raii管理内存的最佳写法【规范】

析构函数必须是 public、noexcept、不带参数

如果你写了 ~MyClass() 却在类外调用它,或者加了参数、返回值、异常说明(比如没写 noexcept),编译器会报错或行为未定义。C++ 标准强制要求析构函数签名固定:~ClassName(),隐式 noexcept(true)。手动加上 noexcept 不仅更明确,还能避免被意外 noexcept 检查拒绝(比如放进 std::vector 时)。

常见错误现象:error: destructor cannot be declared to throw an exception(旧代码里写了 throw(...) 或漏了 noexcept);error: use of deleted function 'MyClass::~MyClass()'(私有析构导致无法自动销毁栈对象或容器元素)。

  • 永远不要把析构函数设为 privateprotected,除非你刻意设计成“只能通过智能指针管理”且已提供配套工厂函数
  • 如果类内有 std::threadFILE*、裸 new 出的内存等资源,析构函数里必须显式清理——不能指望“反正程序快结束了”
  • 别在析构函数里调用虚函数(包括 this->foo()),此时虚表已被部分销毁,行为未定义

RAII 类不该暴露裸指针或手动 delete

RAII 的核心不是“有析构函数”,而是“资源获取即初始化”——构造函数拿到资源,析构函数必然释放,中间不给用户绕过的机会。一旦你提供 get_raw_ptr()release() 之类接口,就等于把资源生命周期控制权交出去了,RAII 就失效了。

使用场景:封装文件句柄、堆内存、锁、socket 连接。典型反例是自己写个 Buffer 类,构造用 new char[...],但还提供 data() 返回 char*,用户可能拿去传给 free() 或重复 delete[]

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

  • 优先用 std::unique_ptrstd::shared_ptr 管理堆内存,而不是手写析构函数做 delete[]
  • 如果真要自定义资源类(比如封装 mmap),构造函数必须完成映射 + 检查失败,析构函数必须调用 munmap,且禁止提供任何可导出底层地址的接口
  • 注意移动语义:若类支持移动(如 Buffer(Buffer&&)),移动后原对象状态必须是“可析构但不可用”,析构函数仍要安全处理空状态(比如检查 ptr_ != nullptrdelete[]

析构函数里禁止抛异常

这是 C++ 最硬的规则之一:~T() 默认是 noexcept,如果它抛了异常且此时栈正在展开(比如另一个异常还没处理完),程序直接调用 std::terminate() 终止,连 catch(...) 都救不了。

DeepSider
DeepSider

浏览器AI侧边栏对话插件,集成多个AI大模型

下载

常见错误现象:std::terminate called without an active exception(实际是析构时抛异常触发的);日志里只看到进程 crash,没留下任何异常信息。

  • 所有可能失败的操作(如 fclose()close()、网络 flush)必须在析构函数里吞掉错误,或记录日志但绝不 throw
  • 如果资源释放逻辑复杂到可能出错(比如需要重试的磁盘刷写),考虑把释放动作拆成显式 shutdown() 方法,让用户在 try/catch 中调用,析构函数只做兜底(比如 log warning)
  • static_assert(noexcept(std::declval<t>().~T()), "...")</t> 可在编译期检查类是否满足 noexcept 析构(适合模板库)

std::vector<:unique_ptr>> 不需要自定义析构函数

很多初学者以为“我要管理一堆对象,所以得写个析构函数遍历 delete”,其实只要用对标准容器和智能指针,编译器生成的默认析构函数就完全够用,且更安全高效。

性能影响:手写循环 delete p 和让 std::vector 自动调用每个 std::unique_ptr 的析构函数,生成的汇编几乎一样;但前者多了人为出错空间(比如漏删、重复删、顺序错)。

  • 正确写法:std::vector<:unique_ptr>> items;</:unique_ptr> —— 插入用 items.push_back(std::make_unique<myclass>(...))</myclass>,析构自动发生
  • 错误写法:std::vector<myclass> raw_ptrs;</myclass> + 手动循环 delete,不仅容易内存泄漏,还会在异常中途退出时崩
  • 如果需要共享所有权,用 std::shared_ptr,但注意循环引用风险;避免混用裸指针和智能指针指向同一块内存

真正难的不是写析构函数,而是判断“这个资源到底该由谁负责释放”。RAII 的规范本质是契约:谁构造,谁销毁;谁持有,谁负责。一旦出现“我传给你一个指针,你记得 delete”的口头约定,就已经脱离 RAII 了。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
fclose函数的用法
fclose函数的用法

fclose是一个C语言和C++中的标准库函数,用于关闭一个已经打开的文件,是文件操作中非常重要的一个函数,用于将文件流与底层文件系统分离,释放相关的资源。更多关于fclose函数的相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

345

2023.11.30

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

493

2023.10.18

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

382

2023.10.25

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

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

1974

2023.10.19

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

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

680

2025.10.17

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

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

2413

2025.12.29

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

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

49

2026.01.19

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

448

2023.07.18

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

69

2026.03.13

热门下载

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

精品课程

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

共94课时 | 11.4万人学习

C 教程
C 教程

共75课时 | 5.5万人学习

C++教程
C++教程

共115课时 | 22.1万人学习

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

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