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&) 两者都不是,所以不能是=defaulted。

【讨论】:

谢谢,现在我知道定义和 =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”构造函数使用初始化列表的主要内容,如果未能解决你的问题,请参考以下文章

:构造函数语意学之Default constructor的构造操作

C++:= default & = delete

C++构造函数的default和delete

C++入门(拷贝)构造函数和析构函数

C++入门(拷贝)构造函数和析构函数

C++函数指针与成员函数指针