and*_*eee 8 c++ default-constructor language-lawyer ctor-initializer c++11
考虑以下类别:
class Foo {
int a, b;
public:
Foo() : a{1}, b{2} {} // Default ctor with member initializer list
//Foo() : a{1}, b{2} = default; // Does not work but why?
};
Run Code Online (Sandbox Code Playgroud)
(编辑:因为在几个答案中都提到了-我知道班级成员的初始化方法,但这不是重点)
我认为第二个ctor定义会更优雅,更适合现代C ++代码(另请参阅为什么=default
必须明确使用默认语义时使用)。但是,似乎没有通用的编译器接受它。而cppreference对此保持沉默。
我首先想到的是,成员初始化程序列表以某种方式更改了“默认语义”,如链接的FAQ中所述,因为它可能会也可能不会默认构造成员。但是对于类内初始化器,我们将遇到同样的问题,只是这里的Foo() = default;
工作很好。
那么,为什么不允许呢?
Sto*_*ica 11
= default;
是一个完整的定义。首先,语法上是强制执行的:
[dcl.fct.def.general]
1函数定义具有以下形式
功能定义: 属性说明符序列opt定义说明符序列opt声明器virt-specifier-seq opt function-body 功能体: ctor初始化程序选择复合语句 功能尝试块 =默认; =删除;
因此,它要么是带有复合语句的成员初始值设定项列表,要么只是plain = default;
,没有mishmash。
此外,= default
表示有关每个成员如何初始化的特定说明。这意味着我们明确希望像编译器提供的构造函数那样初始化所有内容。这与在构造函数的成员初始化器列表中的成员“做一些特别的事情”是矛盾的。
这样做a{1}, b{2}
意味着您不再可以将其指定为default
。每个[dcl.fct.def.default] / 1的默认函数定义为
函数体形式
= default;
为形式的函数定义称为显式默认定义。
并且,如果我们检查[dcl.fct.def.general] / 1中的功能体是什么,我们会发现它包含一个ctor初始化器,它是一个mem-initializer-list
这意味着如果您想要编译器提供的默认定义,则无法初始化成员。
要解决此问题,您可以直接在类中指定默认值,然后将构造函数声明为默认值,例如
class Foo {
int a{1}, b{2};
public:
Foo() = default;
};
Run Code Online (Sandbox Code Playgroud)