It uses the default constructor because list initialization with {}
is meant to be a short form of value initialization always, disregarding of other constructors, even if they are initializer list constructors.
Is there anyway to differentiate the following two constructions: ...
The X()
is always value initialization, while X{}
is only value initialization if X
has a default constructor. If it is an aggregate, then X{}
is aggregate initialization (initializing the members of X
by a {}
recursively). If it only has initializer list constructors and no default constructors, then X()
is invalid and X{}
could be valid
struct A { A(initializer_list<int>); };
A a = A{}; // valid
A b = A(); // invalid
Essentially, what X{}
does depends on what X
is. But X()
always value initializes.
... or return X(); vs return {};
Something subtle to mention... In return {}
the target is copy-list-initialized, while in return X();
first direct-initializes an X
. But even though it is copy-list-initialized, it can use an explicit
default constructor, because value initialization doesn't care about explicit
. However when you do return {}
and you try to use an explicit non-default constructor you will error out
struct A {
explicit A(initializer_list<int>);
};
A f() { return {}; } // error!
struct B {
explicit B();
};
B g() { return {}; } // OK