c++11 聚合初始化之前的值初始化

c++11 value-initialization prior to aggregate-initialization

我试图理解@bolov 对问题 [1]

的第一个接受的答案

我好像在那里发现了一个错误,所以它弄乱了整个解释。

@bolov 解释了为什么这段代码在 c++11 中成功编译:

场景A

struct foo {
  foo() = delete;
};

// All bellow OK (no errors, no warnings)
foo f = foo{};
foo f = {};
foo f{}; // will use only this from now on.

为什么这段代码无法在 c++11 中编译:

场景C

struct foo {
  foo() = delete;
  foo(int) {};
};

foo f{}; // error call to deleted constructor

他说重点是第一个foo是聚合,第二个foo不是聚合。

然后他给出了 cppreference 的摘录:

The effects of list initialization of an object of type T are: ...

  • If T is an aggregate type, aggregate initialization is performed. This takes care of scenarios A B D E (and F in C++14)
  • Otherwise the constructors of T are considered in two phases:

    • All constructors that take std::initializer_list ...

    • otherwise [...] all constructors of T participate in overload resolution [...] This takes care of C (and F in C++11) ...

根据您在 场景 A 中编写 foo f { }; 时的摘录,您将获得聚合初始化。那就太好了。但实际上在 c++11(#3337 草案,最接近标准)中你有 不同的初始化顺序:

List-initialization of an object or reference of type T is defined as follows:

  • If the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
  • Otherwise, if T is an aggregate, aggregate initialization is performed (8.5.1)

因此 foo f { }; 场景 A 中应该导致值初始化,即 DELETED 默认构造函数将是被调用,代码应该编译失败。

由于 Core Issue 1301,这是针对 C++11 的缺陷,列表初始化的优先级从:

List-initialization of an object or reference of type T is defined as follows:

  • If the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
  • Otherwise, if T is an aggregate, aggregate initialization is performed (8.5.1)

至:

List-initialization of an object or reference of type T is defined as follows:

  • If T is an aggregate, aggregate initialization is performed (8.5.1)
  • Otherwise, if the initialize list has no elements and T is a class type with a default constructor, the object is value-initialized.

所以场景A中的foo{}仍然是聚合初始化