C++ primer 说我们可以为“=default”构造函数使用初始化列表

C++ primer says that we can use initializer list for "=default" constructors

struct SalesData {

    SalesData() = default;
    SalesData(const string&s) : bookNo(s) {}

    string bookNo;
    unsigned copies_sold = 0;
    double revenue = 0;
};

在讨论默认构造函数时,primer 说我们可以使用关键字“=default”来使构造函数成为默认构造函数,就像上面的代码一样。该关键字可以与 class 内的声明一起出现,也可以与 class 外的定义一起出现。 如果编译器不能使用 in-class 初始化器,我们可以像第二个构造器一样使用初始化器列表。

但是格式是什么?

首先我尝试直接使用初始化列表:

SalesData() = default:bookNo(""), copies_sold(1), revenue(2){};

但是不行,编译器说不应该有冒号在后面"default"。

然后我尝试在 class 中使用“=default”声明构造函数并在外部定义它,而不使用初始化列表:

struct SalesData {
    SalesData() = default;
   /*...*/}

SalesData::SalesData() {
    bookNo = "";
    copies_sold + 0;
    revenue = 0;
}

编译器说是重定义错误。 然后我把关键字移到了外面,入门书说应该没问题:

struct SalesData {
    SalesData();
   /*...*/}

SalesData::SalesData()=default {
    bookNo = "";
    copies_sold + 0;
    revenue = 0;
}

还是失败了,编译器说"default"后面应该有一个分号。

我用谷歌搜索了类似的问题,但没有找到。

  1. “=default”和初始化列表如何一起工作?

  2. class主体外的“=default”应该如何使用?

如果函数被声明 =default,您不能提供初始化列表(对于构造函数),也不能提供函数体。

要么是书有误,要么是你误解了书上的意思。

在某些情况下,编译器会自动为您生成特殊函数,例如默认构造函数。 =default 是一种明确告诉编译器生成函数的方法,即使在这种情况不会自动发生的情况下也是如此。

重点是:您要么像往常一样自己实现功能要么=default它。您不能为同一功能同时执行这两项操作。影响编译器生成内容的唯一方法是通过默认初始化程序,例如 double revenue = 0;

编译器生成的实现可用于默认构造函数、复制构造函数、复制赋值、移动构造函数、移动赋值和析构函数。有关详细信息,请参阅 this answerSalesData(const string&) 两者都不是,所以不能 =defaulted。

一些补充。

如果您没有在 class 中指定任何构造函数,编译器将生成 default 构造函数。这个构造函数只是用它们的默认(空)构造函数初始化所有成员(当然,如果该构造函数存在,否则它会运行编译错误)。

如果指定非默认构造函数,编译器不会自动生成默认构造函数。您可以在这里找到一些详细信息:

Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?

=default 关键字意味着您 明确地 要求编​​译器生成带有默认主体的默认构造函数(如果您已经指定了另一个)。这意味着此构造函数的 body 是由编译器而不是您创建的。这就是为什么您尝试定义它时会出现编译错误的原因。

请注意,=default 关键字也可用于析构函数。