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"后面应该有一个分号。
我用谷歌搜索了类似的问题,但没有找到。
“=default”和初始化列表如何一起工作?
class主体外的“=default”应该如何使用?
如果函数被声明 =default
,您不能提供初始化列表(对于构造函数),也不能提供函数体。
要么是书有误,要么是你误解了书上的意思。
在某些情况下,编译器会自动为您生成特殊函数,例如默认构造函数。 =default
是一种明确告诉编译器生成函数的方法,即使在这种情况不会自动发生的情况下也是如此。
重点是:您要么像往常一样自己实现功能要么您=default
它。您不能为同一功能同时执行这两项操作。影响编译器生成内容的唯一方法是通过默认初始化程序,例如 double revenue = 0;
编译器生成的实现可用于默认构造函数、复制构造函数、复制赋值、移动构造函数、移动赋值和析构函数。有关详细信息,请参阅 this answer。 SalesData(const string&)
两者都不是,所以不能 =default
ed。
一些补充。
如果您没有在 class 中指定任何构造函数,编译器将生成 default 构造函数。这个构造函数只是用它们的默认(空)构造函数初始化所有成员(当然,如果该构造函数存在,否则它会运行编译错误)。
如果指定非默认构造函数,编译器不会自动生成默认构造函数。您可以在这里找到一些详细信息:
Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?
=default
关键字意味着您 明确地 要求编译器生成带有默认主体的默认构造函数(如果您已经指定了另一个)。这意味着此构造函数的 body 是由编译器而不是您创建的。这就是为什么您尝试定义它时会出现编译错误的原因。
请注意,=default
关键字也可用于析构函数。
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"后面应该有一个分号。
我用谷歌搜索了类似的问题,但没有找到。
“=default”和初始化列表如何一起工作?
class主体外的“=default”应该如何使用?
如果函数被声明 =default
,您不能提供初始化列表(对于构造函数),也不能提供函数体。
要么是书有误,要么是你误解了书上的意思。
在某些情况下,编译器会自动为您生成特殊函数,例如默认构造函数。 =default
是一种明确告诉编译器生成函数的方法,即使在这种情况不会自动发生的情况下也是如此。
重点是:您要么像往常一样自己实现功能要么您=default
它。您不能为同一功能同时执行这两项操作。影响编译器生成内容的唯一方法是通过默认初始化程序,例如 double revenue = 0;
编译器生成的实现可用于默认构造函数、复制构造函数、复制赋值、移动构造函数、移动赋值和析构函数。有关详细信息,请参阅 this answer。 SalesData(const string&)
两者都不是,所以不能 =default
ed。
一些补充。
如果您没有在 class 中指定任何构造函数,编译器将生成 default 构造函数。这个构造函数只是用它们的默认(空)构造函数初始化所有成员(当然,如果该构造函数存在,否则它会运行编译错误)。
如果指定非默认构造函数,编译器不会自动生成默认构造函数。您可以在这里找到一些详细信息:
Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?
=default
关键字意味着您 明确地 要求编译器生成带有默认主体的默认构造函数(如果您已经指定了另一个)。这意味着此构造函数的 body 是由编译器而不是您创建的。这就是为什么您尝试定义它时会出现编译错误的原因。
请注意,=default
关键字也可用于析构函数。