Constructor Init Lists
Part of the Object Oriented Programming section of Coddy's C++ journey — lesson 22 of 104.
You've seen the colon syntax in previous lessons like Player(std::string n, int h) : name(n), health(h) {}. This is called a member initializer list, and it's the preferred way to initialize members in C++.
The initializer list appears after the constructor's parameter list, starting with a colon. Each member is initialized directly with its value, separated by commas:
class Rectangle {
int width;
int height;
const int id;
int& reference;
public:
Rectangle(int w, int h, int i, int& r)
: width(w), height(h), id(i), reference(r) {
// Constructor body (can be empty)
}
};Why use initializer lists instead of assignment in the constructor body? With assignment, members are first default-constructed, then assigned new values. With initializer lists, members are constructed directly with the correct values - more efficient and sometimes required.
Certain members must be initialized using the list:
constmembers - cannot be assigned after construction
- Reference members - must be bound at initialization
- Members without default constructors
class Player {
const int maxHealth; // Must use initializer list
std::string name;
public:
// This works
Player(int max, std::string n) : maxHealth(max), name(n) {}
// This would NOT compile:
// Player(int max) { maxHealth = max; } // Error!
};Members are initialized in the order they're declared in the class, not the order in the initializer list. Always write your initializer list in declaration order to avoid confusion.
Challenge
EasyLet's build a configuration system for a game engine that demonstrates when and why member initializer lists are essential. You'll create a GameConfig class with members that must be initialized using the initializer list syntax.
You'll create two files to organize your code:
GameConfig.h: Define aGameConfigclass that stores game settings. Your class should have:- A
const std::string gameName— the game's title, which cannot change after creation - A
const int maxPlayers— the maximum player count, fixed at construction - An
int& difficultyRef— a reference to an external difficulty setting - An
int screenWidthandint screenHeight— regular members for display settings - A constructor that takes all necessary parameters and initializes every member using the initializer list. The initializer list should follow the order members are declared in the class
- A
display()method that prints the configuration in this format:Game: <gameName> Max Players: <maxPlayers> Difficulty: <difficultyRef value> Resolution: <screenWidth>x<screenHeight>
- A
main.cpp: Read configuration values from input and create a GameConfig object. You'll need:- Read the game name (string), max players (int), difficulty (int), width (int), and height (int) from input — each on a separate line
- Create a local
intvariable for difficulty that the config will reference - Create a
GameConfigobject using the initializer list constructor - Call
display()to show the initial configuration - Modify the difficulty variable directly (multiply it by 2)
- Print
"After difficulty change:" - Call
display()again to show that the reference reflects the updated value
This challenge highlights why initializer lists matter: your const members and reference member cannot be assigned in the constructor body — they must be initialized in the list. The reference member also demonstrates how changes to the original variable are reflected through the config object.
Include your header file in main.cpp using #include "GameConfig.h".
Cheat sheet
A member initializer list is the preferred way to initialize class members in C++. It appears after the constructor's parameter list, starting with a colon, with each member initialized directly:
class Rectangle {
int width;
int height;
public:
Rectangle(int w, int h) : width(w), height(h) {
// Constructor body
}
};Why use initializer lists? Members are constructed directly with the correct values instead of being default-constructed and then assigned, making it more efficient.
Required for certain members:
constmembers - cannot be assigned after construction- Reference members - must be bound at initialization
- Members without default constructors
class Player {
const int maxHealth;
int& reference;
public:
// Correct - uses initializer list
Player(int max, int& r) : maxHealth(max), reference(r) {}
// Error - cannot assign const or reference in body
// Player(int max) { maxHealth = max; }
};Important: Members are initialized in the order they're declared in the class, not the order in the initializer list. Always write your initializer list in declaration order.
Try it yourself
#include <iostream>
#include <string>
#include "GameConfig.h"
using namespace std;
int main() {
// Read input values
string gameName;
getline(cin, gameName);
int maxPlayers;
cin >> maxPlayers;
int difficulty;
cin >> difficulty;
int width;
cin >> width;
int height;
cin >> height;
// TODO: Create a GameConfig object using the initializer list constructor
// The constructor should receive: gameName, maxPlayers, difficulty (by reference), width, height
// TODO: Call display() to show the initial configuration
// TODO: Modify the difficulty variable directly (multiply it by 2)
// TODO: Print "After difficulty change:"
// TODO: Call display() again to show the updated configuration
return 0;
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesC++ Build & CompilationHeader Files & Source FilesNamespaces & ScopeIntroduction to OOP in C++Classes vs ObjectsThe 'this' PointerMethods (Member Functions)Attributes (Data Members)Ctors & Dtors BasicsRecap - Simple Calculator4Class Properties
Instance vs Static MembersGetters and SettersConst Member FunctionsMutable KeywordStatic Methods and VariablesFriend Functions & ClassesRecap - Bank Account Manager7Inheritance
Basic InheritanceInheritance Access LevelsCtor & Dtor Call OrderMethod OverridingVirtual Functions & VTableMultiple InheritanceVirtual InheritanceRecap - Employee Hierarchy2Memory Management
Stack vs Heap MemoryPointers and ReferencesDynamic Memory (new/delete)Smart Pointers in C++RAII in C++Recap - Dynamic Array Manager5Encapsulation
Access Specifiers in C++Access Specifiers In DepthInformation HidingStruct vs ClassNested & Inner ClassesRecap - Student Records System8Polymorphism
Compile vs Runtime PolymorphFunction OverloadingVirtual Functions RevisitedPure Virtual FunctionsAbstract ClassesInterface Design in C++Dynamic Casting & RTTIRecap - Shape Calculator3Constructors & Destructors
Default ConstructorParameterized ConstructorCopy ConstructorMove ConstructorConstructor Init ListsDelegating ConstructorsDestructor Deep DiveRule of Three / Five / ZeroRecap - String Class6Operator Overloading
Intro to Operator OverloadArithmetic Operator OverloadComparison Operator OverloadStream OperatorsAssignment Operator Overload[] and () Operator OverloadType Conversion OperatorsRecap - Matrix Class9Templates
Function TemplatesClass TemplatesTemplate SpecializationVariadic TemplatesSFINAE & Type Traits BasicsRecap - Generic Container