C++ 入门说我们可以为“=default”构造函数使用初始化列表
Posted
技术标签:
【中文标题】C++ 入门说我们可以为“=default”构造函数使用初始化列表【英文标题】:C++ primer says that we can use initializer list for "=default" constructors 【发布时间】:2016-10-08 08:02:42 【问题描述】:struct SalesData
SalesData() = default;
SalesData(const string&s) : bookNo(s)
string bookNo;
unsigned copies_sold = 0;
double revenue = 0;
;
在讨论默认构造函数时,primer 说我们可以使用关键字“=default”来使构造函数成为默认值,就像上面的代码一样。该关键字可以与类内的声明一起出现,也可以与类外的定义一起出现。 如果编译器不能使用类内初始化器,我们可以像第二个构造函数一样使用初始化器列表。
但是格式是什么?
首先我尝试直接使用初始化列表:
SalesData() = default:bookNo(""), copies_sold(1), revenue(2);
但它不起作用,编译器说“默认”后面不应该有冒号。
然后我尝试在类中使用“=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”?
【问题讨论】:
如果你有一个初始化列表,它是一个用户定义的构造函数,而不是默认版本。所以跳过=default
。
=default
用于指定您希望编译器何时为您生成构造函数/赋值。这意味着您无法对其进行定义。它也只适用于默认(我们需要更多的词)、复制和移动构造函数以及相应的赋值,而不是带有 initializer_list 的用户定义的构造函数。
【参考方案1】:
如果函数声明为=default
,则不能提供初始化列表(用于构造函数),也不能提供函数体。
要么这本书是错的,要么你误解了这本书的意思。
【讨论】:
请注意,OP 可能指的是聚合初始化,这对于显式默认的构造函数是允许的,并且它确实使用了初始化列表语法。 谢谢,现在我知道定义和 =default 不能一起使用。但是,C++ 入门书 5th 说,“……在新标准下,如果我们想要默认行为,我们可以通过在参数列表后面写 =default 来要求编译器为我们生成构造函数。=default可以与类体内部的声明一起出现,也可以与类体外部的定义一起出现 ...”那么关于声明和定义的词是什么意思呢? @Dardai 我认为这只是意味着你可以像SalesData() = default;
这样在类内编写它,或者像 SalesData::SalesData() = default;
这样在类外编写它。【参考方案2】:
在某些情况下,编译器会自动为您生成特殊函数,例如默认 ctor。 =default
是一种明确告诉编译器生成函数的方法,即使在不会自动发生的情况下也是如此。
重点是:您要么像往常一样自己实现该功能或您=default
它。你不能为同一个功能做这两个。影响编译器生成内容的唯一方法是通过默认初始化器,例如 double revenue = 0;
编译器生成的实现可用于默认 ctor、复制 ctor、复制分配、移动 ctor、移动分配和析构函数。有关详细信息,请参阅this answer。 SalesData(const string&)
两者都不是,所以不能是=default
ed。
【讨论】:
谢谢,现在我知道定义和 =default 不能一起使用。但是,C++ 入门书 5th 说,“……在新标准下,如果我们想要默认行为,我们可以通过在参数列表后面写 =default 来要求编译器为我们生成构造函数。=default可以与类体内部的声明一起出现,也可以与类体外部的定义一起出现 ...”那么关于声明和定义的词是什么意思呢? @Dardai 您可以将=default
放在其中任何一个位置。虽然它没有使用好词,因为它们都是没有=default
的声明和带有=default
的定义。 (也有语义上的区别,线外的情况不算作user-provided)【参考方案3】:
一些补充。
如果你没有在你的类中指定任何构造函数,编译器会生成 default 构造函数。这个构造函数只是用它们的默认(空)构造函数初始化所有成员(当然如果该构造函数存在,否则它会运行到编译错误)。
如果您指定一个非默认构造函数,编译器不会自动生成默认构造函数。在这里您可以找到一些详细信息:
Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?
=default
关键字意味着您明确要求编译器生成具有默认主体的默认构造函数(如果您已经指定了另一个构造函数)。这意味着这个构造函数的 body 是由编译器而不是你创建的。这就是为什么您尝试定义它时会出现编译错误的原因。
注意=default
关键字也可以在析构函数中使用。
【讨论】:
以上是关于C++ 入门说我们可以为“=default”构造函数使用初始化列表的主要内容,如果未能解决你的问题,请参考以下文章