class A { public: int x[100]; };
Declaring A a
will not initialize the object (to be seen by garbage values in the field x
).
The following will trigger initialization: A a{}
or auto a = A()
or auto a = A{}
.
Should any particular one of the three be preferred?
Next, let us make it a member of another class:
class B { public: A a; };
The default constructor of B
appears to take care of initialization of a
.
However, if using a custom constructor, I have to take care of it.
The following two options work:
class B { public: A a; B() : a() { } };
or:
class B { public: A a{}; B() { } };
Should any particular one of the two be preferred?
class A { public: int x[100]; };
Declaring
A a
will not initialize the object (to be seen by garbage values in the field x).
Correct A a
is defined without an initializer and does not fulfill any of the requirements for default initialization.
1) The following will trigger initialization:
A a{};
Yes;
a{}
performs list initialization which {}
is empty, or could be aggregate initialization if A
is an aggregate.A() = delete;
(If 'A' is still considered an aggregate)2) The following will trigger initialization:
auto a = A();
Yes;
()
which
()
is empty. A
in place.
A(A&&) = delete;
A(const A&) = delete; A(A&&) = default;
3) The following will trigger initialization:
auto a = A{}
Yes;
{}
which
{}
is empty, or could be aggregate initialization if A
is an aggregate. A
in place.
A(A&&) = delete;
A(const A&) = delete; A(A&&) = default;
A() = delete;
(If 'A' is still considered an aggregate)Should any particular one of the three be preferred?
Clearly you should prefer A a{}
.
Next, let us make it a member of another class:
class B { public: A a; };
The default constructor of
B
appears to take care of initialization ofa
.
No this is not correct.
A
, but will not initialize the members. No direct or list initialization will be triggered. Statement B b;
for this example will call the default constructor, but leaves indeterminate values of A
's array.1) However, if using a custom constructor, I have to take care of it. The following two options work:
class B { public: A a; B() : a() { } };
This will work;
: a()
is a constructor initializer and a()
is a member initializer as part of the member initializer list. ()
or, if ()
is empty, value initialization. 2) or:
class B { public: A a{}; B() { } };
This will work;
a
now has a non-static data member initializer, which may require a constructor to initialize it if you are using aggregate initialization and the compiler is not fully C++14 compliant.{}
which {}
is empty or aggregate initialization if A
is an aggregate. a
is the only member then the default constructor does not have to be defined and the default constructor will be implicitly defined.Clearly you should prefer the second option.
Personally, I prefer using braces everywhere, with some exceptions for auto
and cases where a constructor could mistake it for std::initializer_list
:
class B { public: A a{}; };
A std::vector
constructor will behave differently for std::vector<int> v1(5,10)
and std::vector<int> v1{5,10}
. with (5,10)
you get 5 elements with the value 10 in each one, but with {5,10}
you get two elements containing 5 and 10 respectively because std::initializer_list
is strongly preferred if you use braces. This is explained very nicely in item 7 of Effective Modern C++ by Scott Meyers.
Specifically for member initializer lists, two formats may be considered:
a()
which becomes value initialization if the ()
is empty.a{}
which also becomes value initialization if {}
is empty.In member initializer lists, fortunately, there is no risk of the most vexing parse. Outside of the initializer list, as a statement on its own, A a()
would have declared a function vs. A a{}
which would have been clear. Also, list initialization has the benefit of preventing narrowing conversions.
So, in summary the answer to this question is that it depends on what you want to be sure of and that will determine the form you select. For empty initializers the rules are more forgiving.
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