21 August 2022

C++ 核心指南目录

C.31: All resources acquired by a class must be released by the class’s destructor

理由

防止资源泄漏

注意

对于有默认运算符的类,资源可以自动申请释放。

例子

class X {
    ifstream f;   // might own a file
    // ... no default operations defined or =deleted ...
};

类 X 的输入流 ifstream 会在 X 的析构过程中,隐式地关闭其打开的文件。

例子

class X2 {     // bad
    FILE* f;   // might own a file
    // ... no default operations defined or =deleted ...
};

X2 可能会泄露文件句柄(file handle)的内存。

注意

如果套接字不能关闭怎么办?

析构函数、关闭、清理操作不可以失败。

但是如果确实失败了会怎么样?析构函数的开发者不知道什么时候会调用到这个函数,不能通过抛出异常而拒绝后续操作。而且很多关闭/释放操作不能重试。目前来说,没有通用的解决方案。如果行得通,可以认为关闭/清理操作失败的话,本身就是一种设计错误,直接结束程序。

注意

类里面可以有指向不是该类的对象所管理的资源,这些资源通常以指针或引用的方式间接访问。很明显,这些对象不可以在类的析构函数中释放。比如:

Preprocessor pp { /* ... */ };
Parser p { pp, /* ... */ };
Type_checker tc { p, /* ... */ };

这里, p 指向的 pp 不是 p 管理的对象。

强化

  • (简单)如果类中的指针或引用指向的变量属于这个类,那么类的析构函数中也要释放这些资源。
  • (复杂)如果类中有显式的所有权描述语句(比如在构造函数中描述),那么指针和引用成员变量就属于此类。