Goal: to be able list-initialize objects and to have the default
initialization init all PODs to 0/false
with as little boilerplate
as possible (C++11).
Assume I have several classes with several PODs (think of file format
parsing). In order not to deal with undefined values I would like the
default constructed objects to be value-initialized to 0. For example,
providing my own default c'tor that memset()
s this
works fine for
such cases, as does naming all members explicitely.
However, this is boilerplate. Even more importantly providing my own argument-less default constructor prevents me from using the list initializer syntax for member initialization:
class Fails1 {
public:
int a, b;
Fails1() { memset(this, 0, sizeof(*this)); }
};
Fails1 this_works;
Fails1 this_fails{ 42, 54 }; // compiler error
I could add the constructor for the initializer_list
as well, but
that's even more boilerplate. I want to avoid all that boilerplate.
So I looked at the default constructors provided by the compiler when there's no user-provided default constructor in combination with the various methods how one can initialize them. Here's where I got totally confused:
class A {
public:
int a, b;
};
With this class I can use both empty initialization lists and those with values without having to provide both constructors myself; that is part of what I want.
// Example 1: default initialization
A a1;
The first example uses initialization; members a
and b
are
undefined afterwards (not what I want, I want them to be
value-initialized).
// Example 2: Value-initialization, so this works, I guess:
A a2 = A();
Example 2 uses value initialization and does not copy afterwards. So that is what I want, however, I also thought that empty brace-init-lists would do the same; see the following example:
// Example 3: list-initialization with empty brace-init-list
A a3{};
Example 3 is what I thought would do the trick. List initialization
with an empty brace-init-list is described in 8.5.4
"List-initialisation":; especially 8.5.4.3 says: "If the initializer
list has no elements and T is a class type with a default constructor,
the objectvalue-initialized". However, this issues warnings with g++ 4.7.2
with -Wextra
:
missing initializer for member ‘A::a’ [-Wmissing-field-initializers]
missing initializer for member ‘A::b’ [-Wmissing-field-initializers]
No warnings by clang++ 3.1, though, so it may also be a bug in g++.
So back to my original question. How do I value-initialize an object
without having to provide my own boilerplatish default constructor --
while retaining the ability to use list-initialization for its members
without having to provide my own initializer_list
constructor?
A plain struct like
struct A { int a,b; };
is clearly an aggregate, and A a {};
is clearly aggregate initialization and implies value-initialization (i.e. zero-initialization), as described by §8.5.4/3 quoted by you already. (Note in particular the example given there in the following paragraph, which is practically identical to your situation.)
The GCC warning is very misleading.
When searching for existing bug reports, I found this one, which you've filed yourself. I think that was the right thing to do.
Since you've worked out the relevant Standard sections already, and various other people contributed in the comments, I'll make this a Community Wiki answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With