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 specific values within the body of 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 called a member initializer list.

Defining a Member Initializer List

The previous example, where we initialize our Health to 100 from the constructor, can instead be written using a member initializer list. It would look 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 provide a function body for our constructor, within a set of { and } as usual. It can be blank as in the above example, or we can put any other code we might need in there.

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 initially set to some default value. 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, this means we will immediately understand what that part of the code is doing when scanning through 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

If 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 the arguments provided to the constructor. Below, we have a request to create two Character objects, where each request is passing two arguments to a hypothetical constructor:

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

With member initializer lists, we can set our constructor 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 Initializer 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 30 of 61

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 be accurate