我不明白为什么我会这样做:
struct S { int a; S(int aa) : a(aa) {} S() = default; };
为什么不直接说:
S() {} // instead of S() = default;
为什么要为此引入新语法?
默认的默认构造函数被明确定义为与用户定义的默认构造函数相同,没有初始化列表和空的复合语句。
搂12.1/6 [class.ctor] 默认构造函数默认且未定义为已删除,当它被用于创建其类类型的对象或在其第一次声明后显式默认时,它被隐式定义。隐式定义的默认构造函数执行类的一组初始化,这些初始化将由用户编写的该类的默认构造函数执行,没有 ctor-initializer (12.6.2) 和空的复合语句。[…]
但是,虽然两个构造函数的行为相同,但提供空实现确实会影响类的某些属性。提供一个用户定义的构造函数,即使它什么都不做,也会使类型不是 聚合 ,也不是 琐碎 的。如果您希望您的类是聚合类型或普通类型(或通过传递性,POD 类型),那么您需要使用= default.
= default
搂8.5.1/1 [dcl.init.aggr] 聚合是没有用户提供的构造函数的数组或类,[和…] 搂12.1/5 [class.ctor] 如果默认构造函数不是用户提供的并且 […] 搂9/6 [类] 普通类是具有普通默认构造函数和 […]
搂8.5.1/1 [dcl.init.aggr] 聚合是没有用户提供的构造函数的数组或类,[和…]
搂12.1/5 [class.ctor] 如果默认构造函数不是用户提供的并且 […]
搂9/6 [类] 普通类是具有普通默认构造函数和 […]
展示:
#include <type_traits> struct X { X() = default; }; struct Y { Y() { }; }; int main() { static_assert(std::is_trivial<X>::value, "X should be trivial"); static_assert(std::is_pod<X>::value, "X should be POD"); static_assert(!std::is_trivial<Y>::value, "Y should not be trivial"); static_assert(!std::is_pod<Y>::value, "Y should not be POD"); }
constexpr此外,如果隐式构造函数本来就可以显式默认构造函数,并且还会给它提供与隐式构造函数相同的异常规范。在您给出的情况下,隐式构造函数不会constexpr(因为它会使数据成员未初始化)并且它也会有一个空的异常规范,所以没有区别。但是是的,在一般情况下,您可以手动指定constexpr异常规范以匹配隐式构造函数。
constexpr
使用= default确实带来了一些统一性,因为它也可以与复制/移动构造函数和析构函数一起使用。例如,一个空的复制构造函数与默认的复制构造函数(它将执行其成员的成员方式复制)不同。对这些特殊成员函数中的每一个统一使用= default(或= delete)语法,通过明确说明您的意图,使您的代码更易于阅读。
= delete