I have always understood that the default member initializers (introduced
in C++11) merely added that particular initialization value to the
initialization list of a constructor, if it's not explicitly specified
there. In other words, if you do this:
struct A
{
int a = 5, b = 10;
A() {}
A(int v): a(v) {}
};
it results in pretty much the exact equivalent of:
struct A
{
int a, b;
A(): a(5), b(10) {}
A(int v): a(v), b(10) {}
};
The description at
https://en.cppreference.com/w/cpp/language/data_members
seems to corroborate this notion. It says there:
Non-static data members may be initialized in one of two ways:
...
2) Through a default member initializer, which is a brace or equals
initializer included in the member declaration and is used if the
member is omitted from the member initializer list of a constructor.
I can't find any other explanation of the meaning and behavior of default
member initializers. (If another behavior is explained somewhere, I can't
find it.)
All the above is find and dandy, except that the meaning of default member
initializers seems to be rather different with constructorless structs
(and classes, I suppose). Consider this:
//---------------------------------------------------------------------------
#include <iostream>
struct S1 { int a = 5, b = 15, c = 25; };
struct S2 { int a, b, c = 35; };
struct S3 { int a = 1, b, c = 3; };
int main()
{
S1 s1 = { 100 };
S2 s2 = { 200, 300 };
S3 s3 = { 400 };
std::cout << "s1 = { " << s1.a << ", " << s1.b << ", " << s1.c << " }\n"
<< "s2 = { " << s2.a << ", " << s2.b << ", " << s2.c << " }\n"
<< "s3 = { " << s3.a << ", " << s3.b << ", " << s3.c << " }\n";
}
//---------------------------------------------------------------------------
It behaves as you would expect it to behave. The members not specified in
the initialization of the variables get the specified default values. So
this is printed:
s1 = { 100, 15, 25 }
s2 = { 200, 300, 35 }
s3 = { 400, 0, 3 }
But how does that work, exactly? The structs have no user-declared
constructors, so where exactly are those default values being "put",
so to speak? How are the objects constructed from the initializater
lists? Does the compiler, like, create an implicitly constructor
for those structs, with three int parameters with the specified
default values? In other words, is for example S1 above equivalent to:
struct S1
{
int a, b, c;
S1(int ia = 5, int ib = 15, int ic = 25):
a(ia), b(ib), c(ic) {}
};
I think it can't be *completely* equivalent to that because gcc,
if you specify -Wextra, will issue a warning from the line:
S3 s3 = { 400 };
warning: missing initializer for member 'S3::b'
s3.b will be initialized to 0 (IIRC this is guaranteed), but gcc
will still give a warning (if enough warning flags are turned on).