user1095108
user1095108

Reputation: 14603

list vs direct aggregate initialization of implicitly initialized fields

If we contrast list initialization of an aggregate and direct initialization of an aggregate, if I don't specify initializers for all fields, then I suppose the following applies:

For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:

  • If the element has a default member initializer, the element is initialized from that initializer. (since C++11)
  • Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list.
  • Otherwise, the program is ill-formed.

otherwise, if the destination type is a (possibly cv-qualified) aggregate class, it is initialized as described in aggregate initialization except that narrowing conversions are permitted, designated initializers are not allowed, a temporary bound to a reference does not have its lifetime extended, there is no brace elision, and any elements without an initializer are value-initialized.

My question is, what is the difference between copy initialization from an empty initializer list and value-initialization? Maybe a change of language would be in order?

Upvotes: 1

Views: 115

Answers (1)

Artyer
Artyer

Reputation: 40881

One difference would be that value-initialization could not call an initializer-list constructor in the same way copy-init from {} could:

struct A {
    A(std::initializer_list<int>);
};

struct B {
    int i;
    A a;
};

B b1{ 1 };  // OK: `B{ 1, {} }`, or `B{ 1, A(std::initializer_list<int>{}) }`
// B b2(1);  // Error: Cannot value-init an A, it has no default constructor
B b3(1, {});  // Works when copying from `{}`

It appears that GCC/MSVC don't implement this properly, but clang does: https://godbolt.org/z/nj1frf9xv

Upvotes: 3

Related Questions