何时使用 =default 使析构函数默认?

问题描述 投票:0回答:1

虽然对构造函数使用

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

  1. 那些使用
    =default
  2. 那些没有显式定义、由编译器自动生成的。

我唯一想到的是 group-1 析构函数可以定义为虚拟的,但 group-2 始终是非虚拟的。那么,这是它们之间唯一的区别吗?是否存在编译器不生成析构函数,而是使用

=default
强制编译器生成析构函数的情况?

附注我在 stackoverflow 上查了很多问题,但没有一个回答我的问题。以下是一些相关问题。

  1. =default 和 {} ctos/析构函数之间的区别
  2. 默认虚拟析构函数
  3. =default 和空 dtr 之间的区别

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

c++ c++11 destructor
1个回答
10
投票

(以下几点已在评论或链接的问题中提到;此答案用于组织和相互关联它们。)

当然可以通过三种方式获得“简单析构函数”:

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

与默认(而不是复制或移动)构造函数一样,

{}
=default;
对于析构函数来说基本上意味着相同的事情。
Defaulted
的有趣属性是那些与其他属性的 both 不同的(组合)。

Empty
的主要区别很简单:显式默认的析构函数可以是琐碎的。仅当它在类内默认时才适用,因此在外线定义上
{}
=default;
之间没有区别。类似地,虚拟化消除了任何区别,就像任何具有重要析构函数的成员或基类一样。还有一个区别是显式默认的析构函数可以隐式“定义”为“删除”。这两个属性都与隐式声明的析构函数共享,因此我们也必须找到它们之间的区别。 Implicit 相比,显式默认的析构函数抑制移动操作,可以声明为

private

protected
noexcept(false)
,并且在 C++20 中可以受到约束(但不是 consteval
)。非常轻微的是,可以声明 
constexpr
来验证它无论如何都会如此。声明它
inline
没有任何作用。 (它也可以是脱离线或虚拟的,但如上所述,这不能成为使用它的理由。)

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


© www.soinside.com 2019 - 2024. All rights reserved.