c++ destructor析构函数作用_c++资源释放教程

11次阅读

析构函数对象生命周期结束时自动调用,包括局部对象离开作用域、动态对象被delete、临时对象表达式结束、容器销毁元素;未配对delete将导致析构函数不执行,引发资源泄漏。

c++ destructor析构函数作用_c++资源释放教程

析构函数什么时候被调用

析构函数在对象生命周期结束时自动执行,不是你手动调用的。关键触发时机包括:局部对象离开作用域动态分配对象被 delete临时对象结束其表达式生命周期容器销毁元素(如 std::vector 被析构)

注意:如果对象是通过 new 分配但没配对 delete,析构函数永远不会运行 —— 这就是内存泄漏+资源泄漏的根源。

为什么不能只靠 delete 就释放资源

delete 的行为分两步:先调用析构函数,再归还内存。但如果你在析构函数里没写清理逻辑,delete 也救不了你。

常见误区是以为“只要 delete p; 就万事大吉”。实际上:

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

  • 文件句柄(FILE*)不会自动 fclose()
  • 动态分配的内存(int* buf = new int[100];)不会自动 delete[] buf;
  • windows 的 HANDLElinuxint fd 不会自动关闭
  • 第三方库资源(如 OpenGL 的 GLuint texture_id)不会自动 glDeleteTextures()

这些都得在析构函数里显式处理。

析构函数里该写什么、不该写什么

该写:释放内存关闭文件/套接字解锁互斥量(需确保不抛异常)调用对应的 cleanup API(如 SDL_QuitSubSystem)

不该写:throw 异常c++11 起默认为 noexcept,抛异常会直接调用 std::terminate)、调用虚函数(可能已开始析构基类)访问已析构的成员子对象

示例:一个管理文件的简单类

class FileGuard {     FILE* fp_; public:     FileGuard(const char* name) : fp_(fopen(name, "r")) {}     ~FileGuard() {         if (fp_) fclose(fp_); // 必须检查空指针     }     // 禁用拷贝,避免双 fclose     FileGuard(const FileGuard&) = delete;     FileGuard& operator=(const FileGuard&) = delete; };

RaiI 是析构函数的核心使用场景

RAII(Resource Acquisition Is Initialization)不是语法特性,而是一种模式:把资源获取放在构造函数,释放放在析构函数。这样只要对象存在,资源就有效;对象一销毁,资源必然释放 —— 即使中途抛异常也不会漏。

标准库大量使用它:std::unique_ptr 析构时自动 deletestd::fstream 析构时自动 close()std::lock_guard 析构时自动 unlock()

自己实现 RAII 类时最容易忽略的点:必须显式禁用拷贝(或实现移动语义),否则两个对象指向同一资源,析构两次就会崩溃(double-free 或 double-close)。

text=ZqhQzanResources