Bitesize Modern C++: Uniform initialization

C++98 has a frustratingly large number of ways of initialising an object.

image

(Note: not all these initialisations may be valid at the same time, or at all. We’re interested in the syntax here, not the semantics of the class X)

One of the design goals in C++11 was uniform initialisation syntax. That is, wherever possible, to use a consistent syntax for initialising any object. The aim was to make the language more consistent, therefore easier to learn (for beginners), and leading to less time spent debugging.

To that end they added brace-initialisation to the language.

As the name would suggest, brace-initialisation uses braces ({}) to enclose initialiser values. So extending the above examples:

image

There are a couple of highlights from the above code:

Integer i is default-initialised (with the value 0). This is equivalent to C++03’s (much more confusing):

image

x1 is explicitly default-constructed. This alleviates the ‘classic’ mistake made by almost all C++ programmers at some point in their career:

image

By extension, this also alleviates C++’s Most Vexing Parse as well. For those not familiar with it, here it is:

image

Most programmers read this as "create an object, adt, and initialise it with a temporary object, ADT()". Your compiler, however, following the C++ parsing rules, reads it as "adt is a function declaration for a function returning an ADT object, and taking a (pointer to) a function with zero parameters, returning an ADT object."

With brace-initialisation, this problem goes away:

image

The compiler cannot parse the above except as "create an object, adt, and initialise it with a temporary object, ADT{}"

The uniform initialisation syntax goal means that brace-initialisation can be used anywhere an object must be initialised. This includes the member initialisation list:

image

In C++98 programmers had the capability to initialise static member variables as part of the class declaration. C++11 extends this to allow default-initialisation of non-static class members. The code:

image

Can be re-written as:

image

The member initialiser code ensures that the member variable will always have a default value, even if it is not explicitly initialised in a member initialiser list. For the example above we have told the compiler to provide the default constructor; which does nothing.

When we create object adt1 the (compiler-supplied) default constructor is called. The member initialisers in the class-definition ensure that the members of adt1 are initialised.

Having the initialisers visible at point-of-instantiation gives the compiler the opportunity to optimise (away) constructor calls and create the object in-situ.

 

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Glennan Carnie

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.
Glennan Carnie

Latest posts by Glennan Carnie (see all)

Dislike (0)

About Glennan Carnie

Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry. He specialises in C++, UML, software modelling, Systems Engineering and process development.
This entry was posted in C/C++ Programming and tagged , , , , , , . Bookmark the permalink.

2 Responses to Bitesize Modern C++: Uniform initialization

  1. Artur says:

    "C++98 has a frustratingly large number of ways of initialising an object."

    And C++11 adds one more on top of that.
    What I'm frustrated about current way C++ is proceeding, is that people are simply repeating what they've heard somewhere without giving it any thought. Can you really say that C++11 has one and only uniform way of initializing things? No you can't. The (sad) truth is that on top of whole gamut of ways to perform initialization in C++98, C++11 and yet another one. How perverted is that?!?

    Like (0)
    Dislike (1)
  2. Rob says:

    Do member initializers inhibit the default constructor from being generated?

    I've noticed inconsistent behavior from compilers I've tested on.

    Like (0)
    Dislike (0)

Leave a Reply