【问题标题】:When to make a destructor defaulted using =default?何时使用 =default 使析构函数默认?
【发布时间】:2019-11-09 22:52:46
【问题描述】:

虽然对构造函数使用 =default 对我来说很清楚(即强制编译器在存在其他 ctor 的情况下创建默认构造函数),但我仍然无法理解这两种析构函数之间的区别:

  1. 那些使用 =default 的人
  2. 那些没有明确定义并由编译器自动生成的。

我唯一想到的是 group-1 析构函数可以定义为虚拟的,但 group-2 始终是非虚拟的。那么,这就是他们之间的唯一区别吗?有没有编译器不生成析构函数,而是使用=default强制编译器生成的场景?

附言我在stackoverflow中检查了很多问题,但没有一个回答我的问题。这里有一些相关的问题。

  1. Difference between =default and {} ctos/destructors
  2. Defaulting virtual destructors
  3. Difference between =default and empty dtrs

编辑 1:This Q 关于 SO,专注于禁用默认移动构造函数,这可以被视为已接受答案中提到的项目之一。

【问题讨论】:

  • 默认使用虚拟或纯虚拟析构函数是我所知道的仅有的两种适用情况。
  • 析构函数本身对于= default 的行为与省略它相同;但是声明的存在抑制了移动构造函数和移动赋值的隐式生成
  • 那些由编译器隐式生成的将需要完整的类型,如果您正在创建 pimpl 类,这是不可能的。然后,您可以在 pimpl 类型完成后,在实现中声明 ~X(); 并执行 ~X() = default;
  • 其他情况:您希望成为protectedprivate。您希望将其放入 .cpp 文件中,这样它就不会被内联。
  • @Aconcagua 我认为主要区别是在使用 =default 或 {} 时是微不足道和非微不足道的,如此答案中所述:stackoverflow.com/a/13578720/896012

标签: c++ c++11 destructor


【解决方案1】:

(以下几点已在 cmets 或链接问题中提及;此答案用于组织和关联它们。)

当然有三种方法可以得到一个“简单的析构函数”:

struct Implicit {};
struct Empty {~Empty() {}};
struct Defaulted {~Defaulted()=default;};

与默认(而不是复制或移动)构造函数一样,{}=default; 对于析构函数的含义大致相同。 Defaulted 的有趣属性是那些与其他两者不同的(组合)。

Empty 的主要区别很简单:显式默认析构函数可以微不足道。这仅适用于在类中默认设置的情况,因此{}=default; 在外联定义上没有区别。类似地,虚拟化消除了任何区别,任何成员或基类都具有非平凡的析构函数。还有一个区别是显式默认的析构函数可以隐式定义deleted。这两个属性都与隐式声明的析构函数共享,因此我们也必须找到它们的区别。

Implicit 相比,显式默认析构函数抑制移动操作,可以声明为privateprotectednoexcept(false),并且在C++20 中可以进行约束(但不是consteval)。非常轻微地,可以将其声明为 constexpr 以验证它无论如何都会是。声明它inline 没有任何作用。 (它也可以是脱机的或虚拟的,但如上所述,这不能成为使用它的理由。)

所以答案是“当您想要一个具有其他特殊属性的微不足道(或可能已删除)的析构函数时”——最有用的是访问控制或noexcept 状态。

【讨论】:

    猜你喜欢
    • 2012-11-14
    • 2018-12-05
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 2014-05-22
    • 2012-07-14
    相关资源
    最近更新 更多