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{}
仍然是聚合初始化
我试图理解@bolov 对问题
我好像在那里发现了一个错误,所以它弄乱了整个解释。
@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{}
仍然是聚合初始化