默认析构函数有什么用?

What are defaulted destructors used for?

我可以理解默认构造函数,因为用户定义的构造函数将禁用编译器生成的构造函数,使对象不可平凡复制等。

在析构函数的情况下,除了更改访问类别之外,考虑到没有用户定义的成员函数可以禁用它们(无论如何都不能重载析构函数),定义默认析构函数有什么用?

// Which version should I choose ? 
struct Example 
{
    //1. ~Example() = default; 
    //2. ~Example() {}
    //3. 
}; 

即使在虚拟析构函数的情况下,默认它们也不会使它们变得微不足道,那么这样做有什么好处呢?

基本上它是关于传达意图,但相当多余。

但如果您使用 std::unique_ptr 作为 class 的成员,则需要在 header 中声明析构函数(但仅声明)。然后你可以让它在源文件中使用默认实现,如下所示:

MyClass:~MyClass() = default;

考虑到您的选择,我会使用第一个或第三个。

微不足道的析构函数遗漏的例外与 derived class' 析构函数有关,而不是基础析构函数。所以 virtual ~Foo() = default; 是保留默认析构函数但将其虚拟化的有用构造。

正如 Nikos Athanasiou 在评论中提到的,默认构造函数使类型可以轻易破坏,而用户定义的构造函数则不能。一个小代码示例将显示它:

#include <iostream>
#include <type_traits>

struct A { ~A() = default; };
struct B { ~B() {} };
struct C { ~C() noexcept {} };

int main() {
  std::cout
    << std::is_trivially_destructible<A>::value
    << std::is_trivially_destructible<B>::value
    << std::is_trivially_destructible<C>::value
    << std::endl;
  return 0;
}

显示器

100

至于虚拟析构函数,与非虚拟析构函数的一致性和Quentin的回答是适当的理由。我的个人建议是尽可能使用默认值,因为这是坚持最规范行为的一种方式。

一个用途是使析构函数 protectedprivate 同时可能保持 class 微不足道:只需将其列在所需的访问说明符之后。

另:在编写classes时,一些程序员喜欢对class的函数进行排序:例如构造函数,然后是析构函数,然后是非 const "mutating" 成员,然后是 const "accessor" 成员,然后是 static 函数。通过能够显式 = default 析构函数,您可以按预期的顺序列出它,并且 reader 看那里就知道不会有另一个放错地方的版本。在大型 classes 中,它可能有一些 documentary/safety 值。

它也给了你一些具体的东西来添加注释,这可以帮助一些文档工具实现注释与销毁相关。