请考虑以下课程:
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?
};
(编辑:因为在几个答案中都提到了-我知道班级成员的姓名缩写,但这不是重点) >
我认为第二个ctor定义会更优雅,更适合现代C ++代码(另请参见why you should use =default
if you have to be explicit about using the default semantics)。但是,似乎没有通用的编译器接受它。而cppreference对此保持沉默。
我首先想到的是,成员初始化程序列表以某种方式更改了“默认语义”,如链接的FAQ中所述,因为它可能会或可能不会默认构造成员。但是对于类内初始化器,我们将遇到同样的问题,只是这里Foo() = default;
可以正常工作。
那么,为什么不允许呢?
答案 0 :(得分:11)
= default;
本身就是一个完整的定义。首先是语法上的强制执行:
[dcl.fct.def.general]
1函数定义的格式为
function-definition: attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt function-body function-body: ctor-initializeropt compound-statement function-try-block = default ; = delete ;
因此它是带有复合语句的成员初始值设定项列表,或者只是纯= default;
,没有杂烩。
此外,= default
表示有关每个成员如何初始化的特定说明。这意味着我们明确要初始化所有内容,就像编译器提供的构造函数一样。这与在构造函数的成员初始化器列表中的成员“做一些特别的事情”是矛盾的。
答案 1 :(得分:7)
执行a{1}, b{2}
意味着您不再可以将其指定为default
。每个[dcl.fct.def.default]/1的默认函数定义为
其函数 function-body 为
= default;
形式的函数定义称为显式默认的定义。
如果我们检查[dcl.fct.def.general]/1中的 function-body 是什么,我们会发现它包含一个ctor-initializer,即mem-initializer-list
这意味着如果希望编译器提供默认定义,则无法初始化成员。
解决此问题的方法是直接在类中指定默认值,然后将构造函数声明为默认值,例如
class Foo {
int a{1}, b{2};
public:
Foo() = default;
};
答案 2 :(得分:3)
这不能直接回答问题,但是c ++的“方法”是使用default member initializer来代替
class Foo {
int a = 1, b = 2;
public:
Foo() = default;
};
您打算使用的语法本身已不再是默认的构造函数。
答案 3 :(得分:2)
这是不允许的,因为根据定义您要尝试执行的操作意味着它不再是默认的构造函数。无论如何,还有一种更优雅的方式来完成您想要的事情:
class Foo {
int a {1};
int b {2};
public:
Foo() = default;
};