为什么我不能将 =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;

};