Member Initializer Lists
This lesson introduces Member Initializer Lists, focusing on their advantages for performance and readability, and how to use them effectively
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.
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