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

标签 c++ memory-management c++14 destructor virtual-destructor

在类(没有直接指针成员)中,我发现定义析构函数有以下 3 种可能性。

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
}

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

这三种不同的选项通常有什么区别?选择其中之一时应考虑什么?

最佳答案

Can/should option (1) always be avoided?

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

What should be considered when selecting one over others?

    1. 和 3. 具有在所有版本的 C++ 中都有效的优势(不考虑 override 说明符)。
  • 和 3. 只要成员可以轻松地破坏,就具有简单的优势。
    1. 和 2. 的优点是允许析构函数与类定义分开定义(示例中没有利用这一点)。例如,如果您有一个指向不完整类型的唯一指针作为成员,这一点至关重要。这是实现 PIMPL 模式时的典型情况。
    1. 和 2. 还具有允许将析构函数显式声明为 virtual 的优点,这对于多态基类通常是必需的。
    1. 缺点是不推荐使用隐式声明的复制构造函数和赋值运算符。这意味着不应依赖它,并且将来可能会停止工作。 1. 和 2. 都有阻止隐式移动构造函数和赋值运算符生成的缺点。因此,如果您使用其中任何一个,那么您还应该声明复制和移动构造函数以及赋值运算符(如果可能,则使用默认值)。
  • 具有写入量和读取量最少的优点,特别是考虑到上一段。

作为粗略的经验法则,如果可能,请使用 3.。如果不可能(例如上面描述的 PIMPL 情况),则使用 2。如果不可能(即需要支持 C++03),则使用 1。

关于c++ - 如何正确实现 C++ 类析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58412354/

相关文章:

c++ - 假设规则和移除分配

c++ - QStandardItemModel appendRow 在调用构造函数后不起作用

c - 使用带有指针的比较运算符来检查它是否在地址范围内?

C 指针和内存 - 理解

c++ - 它在 C++ 标准中的哪个位置记录了用户定义类型的 I/O?

c++ - 智能指针 : Does a 'base' part of an object get created?

c++ - Qt 将动态按钮附加到窗口

c++ - 在没有 std::launder 的情况下将 std::aligned_storage* 重新解释为 T* 是否违反严格别名规则?

c++ - 如何获取绑定(bind)到我正在运行的控制台窗口的进程列表,该窗口也可以在 Windows 2000 中运行?

c - 通过同一结构的另一个成员访问一个结构的成员