为什么我不能将 =default 用于带有成员初始值设定项列表的默认 ctors
Why can't I use =default for default ctors with a member initializer list
考虑以下 class:
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?
};
(Edit: 因为在几个答案中提到过 - 我知道 in-class 成员初始值设定项,但那是不是重点)
我认为第二个 ctor 定义会更优雅并且更适合现代 C++ 代码(另请参见 why you should use =default
if you have to be explicit about using the default semantics)。但是,似乎没有通用编译器接受它。而 cppreference 对此保持沉默。
我的第一个想法是成员初始值设定项列表以某种方式更改 "default semantics",如链接的常见问题解答中所述,因为它可能会或可能不会默认构造成员。但是对于 in-class 初始化器我们会有同样的问题,只是这里 Foo() = default;
工作得很好。
那么,为什么不允许这样做?
这是不允许的,因为根据定义,您尝试做的事情意味着它不再是默认构造函数。无论如何,还有一种更优雅的方式来完成您想要的:
class Foo {
int a {1};
int b {2};
public:
Foo() = default;
};
= default;
是一个完整的定义。它首先在语法上是强制执行的:
[dcl.fct.def.general]
1 Function definitions have the form
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
表示每个成员的初始化方式。这意味着 我们明确地 想要像编译器提供的构造函数那样初始化所有内容。这与 "doing something special" 与构造函数的成员初始值设定项列表中的成员相矛盾。
这并没有直接回答问题,但它是 c++ "way" 是使用 default member initializer 代替,它
class Foo {
int a = 1, b = 2;
public:
Foo() = default;
};
您使用的语法不再是默认的构造函数。
做 a{1}, b{2}
意味着您不能再将其指定为 default
。每个 [dcl.fct.def.default]/1 的默认函数定义为
A function definition whose function-body is of the form = default;
is called an explicitly-defaulted definition.
如果我们检查 function-body 在 [dcl.fct.def.general]/1 we see that it contains a ctor-initializer which is a mem-initializer-list
中的内容
这意味着如果您想要编译器提供的默认定义,则不能初始化成员。
解决此问题的方法是直接在 class 中指定默认值,然后将构造函数声明为默认值,如
class Foo {
int a{1}, b{2};
public:
Foo() = default;
};
考虑以下 class:
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?
};
(Edit: 因为在几个答案中提到过 - 我知道 in-class 成员初始值设定项,但那是不是重点)
我认为第二个 ctor 定义会更优雅并且更适合现代 C++ 代码(另请参见 why you should use =default
if you have to be explicit about using the default semantics)。但是,似乎没有通用编译器接受它。而 cppreference 对此保持沉默。
我的第一个想法是成员初始值设定项列表以某种方式更改 "default semantics",如链接的常见问题解答中所述,因为它可能会或可能不会默认构造成员。但是对于 in-class 初始化器我们会有同样的问题,只是这里 Foo() = default;
工作得很好。
那么,为什么不允许这样做?
这是不允许的,因为根据定义,您尝试做的事情意味着它不再是默认构造函数。无论如何,还有一种更优雅的方式来完成您想要的:
class Foo {
int a {1};
int b {2};
public:
Foo() = default;
};
= default;
是一个完整的定义。它首先在语法上是强制执行的:
[dcl.fct.def.general]
1 Function definitions have the form
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
表示每个成员的初始化方式。这意味着 我们明确地 想要像编译器提供的构造函数那样初始化所有内容。这与 "doing something special" 与构造函数的成员初始值设定项列表中的成员相矛盾。
这并没有直接回答问题,但它是 c++ "way" 是使用 default member initializer 代替,它
class Foo {
int a = 1, b = 2;
public:
Foo() = default;
};
您使用的语法不再是默认的构造函数。
做 a{1}, b{2}
意味着您不能再将其指定为 default
。每个 [dcl.fct.def.default]/1 的默认函数定义为
A function definition whose function-body is of the form
= default;
is called an explicitly-defaulted definition.
如果我们检查 function-body 在 [dcl.fct.def.general]/1 we see that it contains a ctor-initializer which is a mem-initializer-list
中的内容这意味着如果您想要编译器提供的默认定义,则不能初始化成员。
解决此问题的方法是直接在 class 中指定默认值,然后将构造函数声明为默认值,如
class Foo {
int a{1}, b{2};
public:
Foo() = default;
};