List initialization - What changed in C++14?

Viewed 200

enter image description hereThese two lines from cppreference

What is the difference between these two statements ? I don't see any difference

until c++14

If the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed. Otherwise, if T is an aggregate type, aggregate initialization is performed.

since c++14

If T is an aggregate type, aggregate initialization is performed. Otherwise, if the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed.

2 Answers

The difference is which one happens when both conditions apply: if T is an aggregate class (as opposed to an array), which certainly has a default constructor, and the braced-init-list is empty. Of course, to understand why that matters, we then have to distinguish value initialization from aggregate initialization from an empty list.

Value initialization zero-initializes the object and then default-initializes it, which for an aggregate is default-initializing each of its members, so the value-initialization is member-wise (plus zeroing padding). Aggregate initialization initializes each member from {}, which is again value initialization for many types but is default initialization for members of class type with a user-provided default constructor. The difference can be seen in

struct A {A() {} int i;};
struct B {A a;};  // aggregate
B b{};     // i is 0 in C++11, uninitialized in C++14
B b2=B();  // i is 0 in both versions

In C++14 only, aggregates can have default member initializers; that can't contribute to a difference in behavior between the two language versions, of course, but it doesn't behave differently between these two rules anyway (since it replaces only the common default initialization).

The difference is the sequence of checking, so the aggregate type checking is taking place at the first place, and only then the rest.

Related