小编典典

C++11 中的新语法“= default”

all

我不明白为什么我会这样做:

struct S { 
    int a; 
    S(int aa) : a(aa) {} 
    S() = default; 
};

为什么不直接说:

S() {} // instead of S() = default;

为什么要为此引入新语法?


阅读 79

收藏
2022-07-31

共1个答案

小编典典

默认的默认构造函数被明确定义为与用户定义的默认构造函数相同,没有初始化列表和空的复合语句。

搂12.1/6 [class.ctor]
默认构造函数默认且未定义为已删除,当它被用于创建其类类型的对象或在其第一次声明后显式默认时,它被隐式定义。隐式定义的默认构造函数执行类的一组初始化,这些初始化将由用户编写的该类的默认构造函数执行,没有
ctor-initializer (12.6.2) 和空的复合语句。[…]

但是,虽然两个构造函数的行为相同,但提供空实现确实会影响类的某些属性。提供一个用户定义的构造函数,即使它什么都不做,也会使类型不是 聚合 ,也不是
琐碎 的。如果您希望您的类是聚合类型或普通类型(或通过传递性,POD 类型),那么您需要使用= default.

搂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异常规范以匹配隐式构造函数。

使用= default确实带来了一些统一性,因为它也可以与复制/移动构造函数和析构函数一起使用。例如,一个空的复制构造函数与默认的复制构造函数(它将执行其成员的成员方式复制)不同。对这些特殊成员函数中的每一个统一使用= default(或= delete)语法,通过明确说明您的意图,使您的代码更易于阅读。

2022-07-31