C++11 brace/aggregate initialization. When to use it? - c++

After reading up on C++11 and common guidelines surrounding it, I often read about how you should use in-class initialization as well as aggregate initialization.
Here's an example from what seems to be the "old" way of doing things:
class Example
{
public:
// Set "m_x" to "x", "m_y" gets set to the default value of 5
Example(int x) : m_x(x), m_y(5)
{
}
private:
int m_x;
int m_y;
};
And to my understanding this is what people recommend now:
class Example
{
public:
Example(int x) : m_x{x}
{
}
private:
int m_x{0}; // Supposedly {} works too? I guess this would
// only be necessary if I had another constructor
// taking in 0 arguments, so "m_x" doesn't go uninitialized
int m_y{5};
};
My question is: How does this affect pointers, references, and some of the STL classes? What's the best practice for those? Do they just get initialized with {}? Additionally, should I be doing this even if the constructor initializes the variables anyway? (i.e. Writing m_x{} even though it gets set to something else by the constructor anyway)
Thank you.

You can use in-class member initialization and delegating constructors to reduce code duplication. See my answer to a related question: Refactoring with C++ 11.
Member variables of pointer types can be initialized to nullptr using in-class member initialization. Initializing pointers to something else using in-class member initialization does not seem to be useful. You'll have to judge it for your specific use case.
Member variables of reference types will most likely need to be initialized using the initializer list syntax. Initializing references to something else using in-class member initialization does not seem to be useful. You'll have to judge it for your specific use case.
Re. classes from the standard library ... You can certainly initialize container types using in-class member initialization. The following class is perfectly fine.
struct Foo
{
std::vector<int> ar = {20};
};

Related

Initialising template variables using initializer list

I looked at a piece of code and I am trying to understand how it works and so here is a minimal working example
template <typename T>
class A
{
public:
A() : _mem(T()) {};
private:
T _mem;
};
The first thing I was not exactly clear about is the initialisation of _mem in the initialiser list. What is this technique(?) called? If I look in the debugger _mem is set to 0. If there is a c++11 way to do the same thing could I receive some comments on that?
This is just to safeguard against an uninitialized A::_mem when T is a POD type or a built-in type (like an int). Using a constructor initializer list of : _mem(T()) will default construct a T and initialize _mem with it. For example:
struct POD {
int num;
};
// ...
A<POD> a;
Here, a._mem would be unitialized (in this case, this means a._mem.num is unitialized.) The : _mem(T()) prevents that from happening and will initialize a._mem.num to 0.
However, since C++11 you can just use inline initialization instead:
template <typename T>
class A {
public:
A() {};
private:
T _mem{};
};
T _mem{}; will default-construct _mem, which in turn means POD::num will be default-constructed, which for an int means it will be zero-initialized.
If this has a name, I don't know it.
What's happening:
T() constructs a temporary T and Zero Initializes it.
_mem(T()) makes _mem a copy of the temporary T. Note: A modern compiler will almost certainly elide the copy and simply zero initialize _mem. This still requires that T be copy-or-moveable, so _mem(T()) and _mem() are not exactly the same.
The only relevant C++ 11 difference I can think of is you can use curly braces, _mem{T{}}, for List Initialization. Not useful here, but very useful in other circumstances.

How can a compiler generated default constructor be more efficient than a self-written one that does nothing but initialize members?

Triggered by this answer I was reading in the core guidelines:
C.45: Don’t define a default constructor that only initializes data
members; use in-class member initializers instead
The reasoning given is
Reason
Using in-class member initializers lets the compiler generate the
function for you. The compiler-generated function can be more
efficient.
Note that this is specifically about a default constructor that does nothing but initialize the members and the guideline suggests that one should not write such a constructor.
The "bad" example is:
Example, bad
class X1 { // BAD: doesn't use member initializers
string s;
int i;
public:
X1() :s{"default"}, i{1} { }
// ...
};
The "good" example is using in-class member initializers and no user declared constructor:
Example
class X2 {
string s = "default";
int i = 1;
public:
// use compiler-generated default constructor
// ...
};
What can the compiler generated constructor do more efficient than the user-provided one in that particular example (or in any other example)?
Is the initializer list not giving the same opportunities for optimization as in-class initializers?
Short Answer
A defaulted constructor should have the same generated assembly as the equivalent initializer constructor provided that the author includes the correct constexpr and noexcept statuses.
I suspect the "can be more efficient" is referring to the fact that, in general, it will generate more optimal code than the equivalent developer-authored one that misses opportunities such as inline, constexpr, and noexcept.
Long Answer
An important feature that defaulted constructors perform is that they interpret and deduce the correct status for both constexpr and noexcept
This is something that many C++ developers do not specify, or may not specify correctly. Since Core Guidelines targets both new and old C++ developers, this is likely why the "optimization" is being mentioned.
The constexpr and noexcept statuses may affect code generation in different ways:
constexpr constructors ensure that invocations of a constructor from values yielded from constant expressions will also yield a constant expression. This can allow things like static values that are not constant to not actually require a constructor invocation (e.g. no static initialize overhead or locking required). Note: this works for types that are not, themselves, able to exist in a constexpr context -- as long as the constexprness of the constructor is well-formed.
noexcept may generate better assembly of consuming code since the compiler may assume that no exceptions may occur (and thus no stack-unwinding code is necessary). Additionally, utilities such as templates that check for std::is_nothrow_constructible... may generate more optimal code paths.
Outside of that, defaulted constructors defined in the class-body also make their definitions visible to the caller -- which allows for better inlining (which, again, may otherwise be a missed-opportunity for an optimization).
The examples in the Core Guidelines don't demonstrate these optimizations very well. However, consider the following example, which illustrates a realistic example that can benefit from defaulting:
class Foo {
int a;
std::unique_ptr<int> b;
public:
Foo() : a{42}, b{nullptr}{}
};
In this example, the following are true:
A construction of Foo{} is not a constant expression
Construction of Foo{} is not noexcept
Contrast this to:
class Foo {
int a = 42;
std::unique_ptr<int> b = nullptr;
public:
Foo() = default;
};
On the surface, this appears to be the same. But suddenly, the following now changes:
Foo{} is constexpr, because std::unique_ptr's std::nullptr_t constructor is constexpr (even though std::unique_ptr cannot be used in a full constant expression)
Foo{} is a noexcept expression
You can compare the generated assembly with this Live Example. Note that the default case does not require any instructions to initialize foo; instead it simply assigns the values as constants through compiler directive (even though the value is not constant).
Of course, this could also be written:
class Foo {
int a;
std::unique_ptr<int> b;
public:
constexpr Foo() noexcept :a{42}, b{nullptr};
};
However, this requires prior knowledge that Foo is able to be both constexpr and noexcept. Getting this wrong can lead to problems. Worse yet, as code evolves over time, the constexpr/noexcept state may become incorrect -- and this is something that defaulting the constructor would have caught.
Using default also has the added benefit that, as code evolves, it may add constexpr/noexcept where it becomes possible -- such as when the standard library adds more constexpr support. This last point is something that would otherwise be a manual process every time code changes for the author.
Triviality
If you take away the use of in-class member initializers, then there is one last worthwhile point mentioning: there is no way in code to achieve triviality unless it gets compiler-generated (such as through defaulted constructors).
class Bar {
int a;
public:
Bar() = default; // Bar{} is trivial!
};
Triviality offers a whole different direction on potential optimizations, since a trivial default-constructor requires no action on the compiler. This allows the compiler to omit any Bar{} entirely if it sees that the object is later overwritten.
I think that it's important to assume that C.45 refers to constants (example and enforcement):
Example, bad
class X1 { // BAD: doesn't use member initializers
string s;
int i; public:
X1() :s{"default"}, i{1} { }
// ... };
Example
class X2 {
string s = "default";
int i = 1; public:
// use compiler-generated default constructor
// ... };
Enforcement
(Simple) A default constructor should do more than just initialize
member variables with constants.
With that in mind, it's easier to justify (via C.48) why we should prefer in-class initializers to member initializers in constructors for constants:
C.48: Prefer in-class initializers to member initializers in
constructors for constant initializers
Reason
Makes it explicit that the same value is expected to be used in all
constructors. Avoids repetition. Avoids maintenance problems. It leads
to the shortest and most efficient code.
Example, bad
class X { // BAD
int i; string s;
int j; public:
X() :i{666}, s{"qqq"} { } // j is uninitialized
X(int ii) :i{ii} {} // s is "" and j is uninitialized
// ... };
How would a maintainer know whether j was deliberately uninitialized
(probably a poor idea anyway) and whether it was intentional to give s
the default value "" in one case and qqq in another (almost certainly
a bug)? The problem with j (forgetting to initialize a member) often
happens when a new member is added to an existing class.
Example
class X2 {
int i {666};
string s {"qqq"};
int j {0}; public:
X2() = default; // all members are initialized to their defaults
X2(int ii) :i{ii} {} // s and j initialized to their defaults
// ... };
Alternative: We can get part of the benefits from default arguments to
constructors, and that is not uncommon in older code. However, that is
less explicit, causes more arguments to be passed, and is repetitive
when there is more than one constructor:
class X3 { // BAD: inexplicit, argument passing overhead
int i;
string s;
int j; public:
X3(int ii = 666, const string& ss = "qqq", int jj = 0)
:i{ii}, s{ss}, j{jj} { } // all members are initialized to their defaults
// ... };
Enforcement
(Simple) Every constructor should initialize every member variable (either explicitly, via a delegating ctor call or via default
construction).
(Simple) Default arguments to constructors suggest an in-class initializer may be more appropriate.

What's the differences between member initializer list and default member initializer on non-static data member?

I'd like to understand what's the differences of using one form rather than the other (if any).
Code 1 (init directly on variables):
#include <iostream>
using namespace std;
class Test
{
public:
Test() {
cout<< count;
}
~Test();
private:
int count=10;
};
int main()
{
Test* test = new Test();
}
Code 2 (init with initialization list on constructor):
#include <iostream>
using namespace std;
class Test
{
public:
Test() : count(10) {
cout<< count;
}
~Test();
private:
int count;
};
int main()
{
Test* test = new Test();
}
Is there any difference in the semantics, or it is just syntactic?
Member initialization
In both cases we are talking about member initialization.
Keep in mind that the members are initialized in the sequence in which they are declared in the class.
Code 2: Member initializer list
In the second version:
Test() : count(10) {
: count(10) is a constructor initializer (ctor-initializer) and count(10) is a member initializer as part of the member initializer list. I like to think of this as the 'real' or primary way that the initialization happens, but it does not determine the sequence of initialization.
Code 1: Default member initializer
In the first version:
private:
int count=10;
count has a default member intitializer. It is the fallback option. It will be used as a member initializer if none is present in the constructor, but in the class the sequence of members for initialization is determined.
From section 12.6.2 Initializing bases and members, item 10 of the standard:
If a given non-static data member has both a
brace-or-equal-initializer and a mem-initializer, the initialization
specified by the mem-initializer is performed, and the non-static data
member’s brace-or-equal-initializer is ignored. [ Example: Given
struct A {
int i = / some integer expression with side effects / ;
A(int arg) : i(arg) { }
// ...
};
the A(int) constructor will simply initialize i to the value of arg,
and the side effects in i’s brace-or-equalinitializer will not take
place. —end example ]
Something else to keep in mind would be that if you introduce a non-static data member initializer then a struct will no longer be considered an aggregate in C++11, but this has been updated for C++14.
Differences
what's the differences of using one form rather than the other (if
any).
The difference is the priority given to the two options. A constructor initializer, directly specified, has precedence. In both cases we end up with a member initializer via different paths.
It is best to use the default member initializer because
then the compiler can use that information to generate the constructor's initializer list for you and it might be able to optimize.
You can see all the defaults in one place and in sequence.
It reduces duplication. You could then only put the exceptions in the manually specified member initializer list.
In the C++ Core Guidelines (see note 1 below), Guideline C.48 recommends the first approach (in-class initializers.) The reasoning provided is:
Makes it explicit that the same value is expected to be used in all constructors. Avoids repetition. Avoids maintenance problems. It leads to the shortest and most efficient code.
In fact if your constructor does nothing but initialize member variables, as in your question, then Guideline C.45 is firmer still, saying to use in-class initializers for sure. It explains that
Using in-class member initializers lets the compiler generate the function for you. The compiler-generated function can be more efficient.
I am not going to argue with Stroustrup, Sutter, and several hundred of their friends and colleagues even if I haven't written a compiler so I can't prove it's more efficient. Use in-class initializers wherever you can.
If you're not familiar with the guidelines do follow the links to see sample code and more explanations.
The difference I can think of is that member initializer list is prior to default member initializer.
Through a default member initializer, which is simply a brace or
equals initializer included in the member declaration, which is used
if the member is omitted in the member initializer list.
If a member has a default member initializer and also appears in the
member initialization list in a constructor, the default member
initializer is ignored.
For example:
class Test
{
public:
Test() {} // count will be 10 since it's omitted in the member initializer list
Test(int c) : count(c) {} // count's value will be c, the default member initializer is ignored.
private:
int count = 10;
};
There is no difference in the code. The difference would come if you would be would have more than one constructor overload and in more than one count would be 10. With the first version you would have less writing to do.
class Test
{
public:
Test() = default;
Test(int b) : b(b) {} // a = 1, c = 3
~Test();
private:
int a = 1;
int b = 2;
int c = 3;
};
As opposed to the second version where the above code would look like this:
class Test
{
public:
Test() : a(1), b(2), c(3) {}
Test(int b) : a(1), b(b), c(3) {}
~Test();
private:
int a;
int b;
int c;
};
The difference gets bigger with more member variables.
When you initialise next to the declaration of the member, this is valid only in C++11 onwards, so if you're in C++98/03 you outright cannot do this.
If the value never changes, you could choose to make this a constexpr static instead and the compiler would then be required to not use any extra storage for the value (so long as you don't define it) and instant use constant propagation wherever the value is used instead.
One disadvantage of using the by-declaration syntax is that it must be in the header, which will result in a recompile of all translation units that include the header every time you want to change its value. If this takes a long time, that might be unacceptable.
Another difference is that using the member initialisation list lets you change the value for each constructor, whilst using the by-declaration version only allows you to specify one value for all constructors (although you could overwrite this value ... but I'd personally avoid this as it could get quite confusing!).
As an aside, there's no need to use new here to create an instance of Test. This is a common mistake when people come to the language from other languages and I wanted to make you aware. There are of course many uses for doing this outside of your example.

How to define a Struct with default values?

Rather surprised to find this question not asked before. Actually, it has been asked before but the questions are VERY DIFFERENT to mine. They are too complicated and absurd while I'll keep it simple and to the point. That is why this question warrants to be posted.
Now, when I do this,
struct A {
int a = -1;
};
I get the following error:
ANSI C++ forbids in-class initialization of non-const static member a
Now, along with the workaround can someone please tell me THE BEST way of initializing a struct member variable with a default value?
First, let's look at the error:
ANSI C++ forbids in-class initialization of non-const static member a
Initialization of a true instance member, which resides within the memory of an instance of your struct is the responsibility of this struct's constructor.
A static member, though defined inside the definition of a particular class/struct type, does not actually reside as a member of any instances of this particular type. Hence, it's not subject to explaining which value to assign it in a constructor body. It makes sense, we don't need any instances of this type for the static member to be well-initialized.
Normally, people write member initialization in the constructor like this:
struct SomeType
{
int i;
SomeType()
{
i = 1;
}
}
But this is actually not initialization, but assignment. By the time you enter the body of the constructor, what you've done is default-initialize members. In the case of a fundamental type like an int, "default-initialization" basically boils down to "eh, just use whatever value was in those bytes I gave you."
What happens next is that you ask i to now adopt the value 1 via the assignment operator. For a trivial class like this, the difference is imperceptible. But when you have const members (which obviously cannot be tramped over with a new value by the time they are built), and more complex members which cannot be default-initialized (because they don't make available a visible constructor with zero parameters), you'll soon discover you cannot get the code to compile.
The correct way is:
struct SomeType
{
int i;
SomeType() : i(1)
{
}
}
This way you get members to be initialized rather than assigned to. You can initialize more than one by comma-separating them. One word of caution, they're initialized in the order of declaration inside your struct, not how you order them in this expression.
Sometimes you may see members initialized with braces (something like i{1} rather i(c)). The differences can be subtle, most of the time it's the same, and current revisions of the Standard are trying to smooth out some wrinkles. But that is all outside the scope of this question.
Update:
Bear in mind that what you're attempting to write is now valid C++ code, and has been since ratification of C++11. The feature is called "Non-static data member initializers", and I suspect you're using some version of Visual Studio, which still lists support as "Partial" for this particular feature. Think of it as a short-hand form of the member initialization syntax I described before, automatically inserted in any constructor you declare for this particular type.
You could make a default constructor
struct A {
A() : a{-1} {}
int a;
};

Initializing in constructors, best practice?

I've been programming in C++ a while and I've used both methods:
class Stuff {
public:
Stuff( int nr ) : n( nr ) { }
private:
int n;
}
Or
class Stuff {
public:
Stuff( int nr ) {
n = nr;
}
private:
int n;
}
Note: This is not the same as this, similar but not the same.
What is considered best practice?
Initializer lists are preferred. See FAQ 10.6
One big advantage to using initializers: If an exception is thrown anywhere within the initializer list, the destructors will be called for those members that had already been initialized -- and only for those members.
When you use the contructor body to initialize the object, it's up to you to handle exceptions properly and unwind the object as appropriate. This is usually much harder to get right.
Use the initializer list when possible. For an int, it doesn't matter much either way, but for a more complex member object, you'd end up with the default constructor of the object being called, followed by an assignment to that object, which is likely to end up being slower.
Plus, you have to do it that way anyway for const members or members which don't have a default constructor.
If possible, use the first version.
The first is initializing using intializer lists, and actually calls the constructors of the members.
The second is assignment. If n was of a type with a default constructor, it the would have already been called, and then you'd be assigning to it. If n didn't have a default constructor, you'd be forced to use the first type. Likewise if n was a reference: int &n.
If there are no constructors of you members that directly take one of the parameters to your constructor, it may be worthwhile to add private static functions that can do the conversion for you.
I generally try to do the initializer list when I can. For one thing, this makes it explicit that you are initializing code in the constructor. const memebers have to be initialized this way.
If you just put code in the constructor's body, it is quite possible someone may decide to come along and move a big chunk of it into a non-constructor "setup" routine later.
It can be taken overboard though. I have a coworker who likes to create classes that have 2 pages of initilizer code, no constructor code, and perhaps 2 pages for the entire rest of the class' code. I find that really tough to read.
I want to add that you don't need to declare the initializer list on the Header (.h). It can be done at the implementation of the constructor (which is very common).
So then:
//Stuff.h
class Stuff {
public:
Stuff( int nr );
private:
int n;
}
//Stuff.cpp
Stuff::Stuff(int nr)
: n(nr)
{
//initalize complex members
}
is legal and imo concentrates the initialization of fields where it matters. Sometimes we need to initialize complex members in the body, so you have your initializer list and the complex initialization all in the .cpp file.
The second option is not initialization but assignment. With types that have user defined default constructors, the second option will call the default constructor and later on call the assignment operator (whether user defined or not) to assign the value.
Some types cannot be default initialized: If you have an attribute without default constructor, hold references (constant or not) or have constant attributes they must be initialized in the initializer list.
Arrays can be value-initialized in the initialization list, but not in the constructor body:
class X {
public:
X() : array() {} // value-initializes the array
// equivalent to:
// X() { for ( int i = 0; i < 10; ++i ) array[i]=0; }
private:
int array[10];
};
For POD types, you can value-initialize them in the initialization list but not inside the brackets:
class X {
public:
X() : pod() {} // value-initializes
// equivalent to (but easier to read and subtly faster as it avoids the copy):
// X() { pod = {}; }
private:
PODType pod;
};
Finally, some classes offer functionality through the use of constructors that will be more complex (if achievable) after default construction.
class X
{
public:
X() : v(10) {} // construct a vector of 10 default initialized integers
// equivalent to:
// X() { for ( int i = 0; i < 10; ++i ) v.push_back(0); }
private:
std::vector<int> v;
};
Last, whenever they are in fact equivalent, initialization lists are more idiomatic in C++.