CppCoreGuidelines C.31 类获取的所有资源必须在析构函数中释放
21 August 2022
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
管理的对象。
强化
- (简单)如果类中的指针或引用指向的变量属于这个类,那么类的析构函数中也要释放这些资源。
- (复杂)如果类中有显式的所有权描述语句(比如在构造函数中描述),那么指针和引用成员变量就属于此类。