Member Initializer Lists

This lesson introduces Member Initializer Lists, focusing on their advantages for performance and readability, and how to use them effectively

Ryan McCombe
Updated

In previous lessons, we saw how we could initialize the members of our classes to different values, using a constructor:

class Character {
public:
  Character() {
    mHealth = 100;
  }

private:
  int mHealth;
};

Constructors and Destructors

Learn about special functions we can add to our classes, control how our objects get created and destroyed.

C++ provides a dedicated syntax for this purpose, that we can use with constructors. This syntax is called a member initializer list.

Defining a Member Initializer List

The previous example, where we initialize our Health to 100 from the constructor, can be written using a member initializer list like this:

class Character {
public:
  Character() : mHealth{ 150 } {
    // Body here
  }

private:
  int mHealth;
};

We place the initializer list between the name and the body of the function, separated by a :.

We still can provide a function body for our constructor. It can be blank as in the above example, or we can put any other code in there that we want to run when our objects are first created.

If we do not need to provide a body, we still have to include the braces { and }.

Test your Knowledge

Using a Member Initialiser List

How can we update the following class to use a member initializer list?

class Weapon {
public:
  Weapon() {
    mDamage = 150;
  }

  int mDamage;
};

Why use a Member Initializer List?

Member initializer lists have three main advantages over writing equivalent code in the constructor body:

Performance

Due to nuance in how objects are constructed, initializing variables in a constructor body is slightly slower than it needs to be.

When our object is created, memory is assigned for its variables, and set to some default value before. This happens before our constructor body is executed.

If our constructor body then changes the value of those variables, we have to revisit and update those memory locations.

By specifying initial values in a dedicated initializer list, the compiler can identify and optimize that process to a single step.

Code Readability

Member initializer lists are dedicated to initializing our class members.

Once we get familiar with the syntax, we will immediately understand what that part of the code is doing when reading other files.

It's Sometimes Required

In some scenarios, using a member initializer list is required to get the desired functionality. We'll see an example of this in the next lesson, and more examples later in the course.

Initializing Multiple Members

Where we want to initialize multiple class variables, we can add those to the list, separated by commas:

class Character {
public:
  Character() : mHealth{ 150 }, mLevel{ 5 } {
    // Body here
  }

private:
  int mHealth;
  int mLevel;
};

Using Expressions in Member Initializer Lists

Like with the initialization of any other variables, any expression that results in a value of the correct type can be used.

This is shown in the below example. Remember, C++ is not especially sensitive to white space, so we can generally add line breaks and additional space where needed if we think it makes our code more readable:

int GetLevel() { return 5; }

class Character {
public:
  Character() :
    mHealth{ 100 + 50 },
    mLevel{ GetLevel() }
  {
    // Body here
  }

private:
  int mHealth;
  int mLevel;
};

Using Parameters in Member Initializer Lists

Of course, the above examples are slightly unnecessary. The previous examples don't need an initializer list (or a constructor) at all - we could just do this:

class Character {
  int mHealth { 100 + 50 };
  int mLevel { GetLevel() };
};

However, the strength of initializing variables from constructors is that we can use parameters passed in by the code seeking to construct an object from our class:

Character SmallCharacter { 150, 5 };
Character BigCharacter { 300, 15 };

With member initializer lists, we can set our constructors up to support this as follows:

class Character {
public:
  Character(int Health, int Level) :
    mHealth{Health},
    mLevel{Level}
  {
    // Body here
  }

private:
  int mHealth;
  int mLevel;
};

Test your Knowledge

Using a Member Initialiser List

How can we update the following class to use a member initializer list?

class Weapon {
public:
  Weapon(int Damage) {
    mDamage = Damage;
  }

  int mDamage;
};

Summary

In this lesson, we explored the use of Member Initializer Lists. We learned that these lists offer a more efficient way to initialize class members, enhancing both performance and code readability. Key points include:

  • Member Initializer Lists allow for direct initialization of class members.
  • They provide performance benefits by reducing the number of operations during object creation.
  • These lists enhance code clarity, making the initialization intent explicit.
  • In certain scenarios, Member Initializer Lists are necessary for correct class functionality.
  • We can initialize multiple members and use expressions and constructor parameters in these lists.
Next Lesson
Lesson 29 of 60

Working with Inherited Members

This lesson provides an in-depth exploration of using inherited methods and variables in C++, covering constructor calls, variable modification, and function shadowing

Have a question about this lesson?
Answers are generated by AI models and may not have been reviewed for accuracy