如何正确实现C ++类的析构函数

Sum*_*udu 3 c++ destructor memory-management virtual-destructor c++14

在一个类(没有直接指针成员)中,我看到了以下三种定义析构函数的可能性。

class Child : public Parent
{
public:
    // ~Child() override {}          // (1) explicit destructor with empty body
    // ~Child() override = default;  // (2) explicit default destructor
    //                               // (3) implicit default destructor


private:
    // members
}
Run Code Online (Sandbox Code Playgroud)

是否可以/应该(1)始终避免选择?因为(2)当我使用option时,Clang-Tidy会提示我采用option (1)

三种不同的选择之间的一般区别是什么?选择一个以上时应考虑什么?

eer*_*ika 5

是否可以/应该始终避免选择(1)?

假设该语言是非古代版本,是的。据我所知,使用空非默认析构函数的唯一原因是支持C ++ 03和更早的标准。

选择一个以上时应考虑什么?

    1. 3.具有在所有C ++版本中都有效的优点(降低了override说明符)。
    1. 3.只要成员是易碎的,就具有琐碎的优势。
    1. 2.具有可以将析构函数与类定义分开定义的优点(本示例中未利用)。例如,如果您有一个指向不完整类型的唯一指针作为成员,则这至关重要。这在实现PIMPL模式时很典型。
    1. 2.还具有允许将析构函数显式声明为虚拟的优点,这通常是多态基类所必需的。
    1. 缺点是不建议使用隐式声明的副本构造函数和赋值运算符。这意味着不应依赖它,将来可能会停止工作。1.和2.都具有阻止隐式移动构造函数和赋值运算符生成的缺点。因此,如果您使用两者之一,则还应该声明复制并移动构造函数和赋值运算符(如果可能的话,默认设置)。
    1. 具有最少写入量和最少读取量的优点,尤其是考虑到上一段。

根据经验,尽可能使用3.。如果不可能(例如,上述PIMPL情况),则使用2。如果不可能(即,您需要支持C ++ 03),则使用1。

  • 同样,1.(我认为也是2.)也具有禁用隐式生成移动ctor / assignment的缺点。 (3认同)