虽然对构造函数使用
=default
对我来说很清楚(即强制编译器在其他构造函数存在时创建默认构造函数),但我仍然无法理解这两种类型的析构函数之间的区别:
=default
我唯一想到的是 group-1 析构函数可以定义为虚拟的,但 group-2 始终是非虚拟的。那么,这是它们之间唯一的区别吗?是否存在编译器不生成析构函数,而是使用
=default
强制编译器生成析构函数的情况?
附注我在 stackoverflow 上查了很多问题,但没有一个回答我的问题。以下是一些相关问题。
编辑1:这个Q关于SO,重点是禁用默认的移动构造函数,这可以被视为已接受答案中提到的项目之一。
(以下几点已在评论或链接的问题中提到;此答案用于组织和相互关联它们。)
当然可以通过三种方式获得“简单析构函数”:
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
状态。