问题
I'm reading the C++11 standard, but can't figure out whether
T x{};
is value-initialized or default initialized (automatic storage). It does say pretty clearly that:
10 An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
And that
11 If no initializer is specified for an object, the object is default-initialized;
But all I can find about T x{};
is that:
The initialization that occurs in the forms T x(a); T x{a}; as well as in new expressions (5.3.4), static_cast expressions (5.2.9), functional notation type conversions (5.2.3), and base and member initializers (12.6.2) is called direct-initialization.
and
If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized (8.5.4).
I'm new to diving into the level of reading the standards. Can someone point me in the right direction?
回答1:
This is indeed covered by your quote:
If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized (8.5.4).
Skipping down to 8.5.4 List-initialization. Here I have paraphrased/omitted some points that don't pertain to the case of T x{}
:
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 initializer list has no elements and T is a class type with a default constructor, the object is value-initialized
- Otherwise, if
T
is a specialization ofstd::initializer_list<E>
[...]- Otherwise, [if the list is not empty and it matches a constructor]
- Otherwise, [if the list has a single element]
- Otherwise, [if
T
is a reference type]- Otherwise, if the initializer list has no elements, the object is value-initialized.
- Otherwise, the program is ill-formed.
The first point, aggregate initialization was in C++03 as well; in that case T x{};
is the same as T x = {};
.
For the second point "T is a class type with a default constructor", it is value-initialized which means calling the default constructor.
If T
is a primitive type then the second-to-last point applies and it is value-initialized again.
Going back to the aggregate initialization case, in 8.5.1/7 there is:
If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equal-initializer, from an empty initializer list (8.5.4).
The brace-or-equal-initializer refers to an initializer provided inline in the class definition. If that isn't present then it is initialized as if the member had been initialized with {}
(so, this logic is recursively applied for each aggregate member).
For example,
struct T
{
int a;
};
then T x {};
leads to a
being initialized as if it were int a{};
, which is value-initialization since int
is a primitive type.
回答2:
Although Matt McNabb has already covered this, I will add that if you have trouble navigating through the standard, it doesn't hurt to check out cppreference. Their section on list initialization breaks it down pretty well.
Essentially, like your standard quote says, T x{};
refers to an:
initialization of a named variable with a brace-enclosed list of expressions or nested lists (braced-init-list).
And:
The effects of list initialization of an object of type T are:
- If the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed.
[...]
- Otherwise, if the braced-init-list has no elements, T is value-initialized.
来源:https://stackoverflow.com/questions/25964198/t-v-initialization