According to the accepted (and only) answer for this Stack Overflow question,
Defining the constructor with
MyTest() = default;
The difference in behaviour comes from the fact that, according to [dcl.fct.def.default]/5, bar::bar
is user-provided where foo::foo
is not1. As a consequence, foo::foo
will value-initialize its members (meaning: zero-initialize foo::a
) but bar::bar
will stay uninitialized2.
1) [dcl.fct.def.default]/5
A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
2)
From [dcl.init#6]:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type with either no default constructor ([class.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
...
From [dcl.init.list]:
List-initialization of an object or reference of type T is defined as follows:
...
Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
From Vittorio Romeo's answer