避免显式调用析构函数
10.6.4 ID_explicitDtorCall
何时调用析构函数应由语言的底层机制决定,程序不宜显式调用析构函数。
显式调用析构函数后,应释放对象的内存空间并舍弃对象,或者重新构造对象,否则访问对象的任何非静态成员都会导致标准未定义的行为。显式调用析构函数会提前结束对象的生命周期,易被误用,不应作为惯用方法。
示例:
class A {
int* p = new int[123];
public:
~A() { delete[] p; }
};
void foo() {
A a;
a.~A(); // Non-compliant, explicitly call the destructor
} // ~A() twice called, crash
例中对象 a 的析构函数被显式调用,foo 返回前会再次调用析构函数,造成内存被重复释放。应去掉显式调用,由类提供提前释放资源的方法,并保证资源不会被重复释放。
处理专用硬件资源或开发资源管理设施时,显式析构可能是必要的,一般与“placement new”配合使用,如:
size_t n = sizeof(A);
alignas(A) byte buf[n];
A* p = new(buf) A; // Place an object of ‘A’ into the pre-allocated ‘buf’
p->~A(); // OK, used with the placement new
例中 new(buf) A 在指定的内存空间中构造对象,通过这种方式构造的对象可被显式析构。
依据
ISO/IEC 14882:2003 12.4(14)-undefined
ISO/IEC 14882:2011 12.4(15)-undefined
ISO/IEC 14882:2017 15.4(15)
ISO/IEC 14882:2017 15.4(16)-undefined