1. Introduction to Constructor Initializer List
In this article, we will learn what is Constructor Initializer List. The initializer list is helpful to load the data members of a class with a default data. It performs this initialization stuff before executing the body.
2. A Class With a Constant Data Member
Let us say a class is having a const data member in it. Where should we initialize it? We explore this with an example.
Let us say, we have a class called circle which calculates area when a radius available to it. We need a data member to hold the value of the constant Pi. In the below constructor, we attempt to initialize data members radius and the const Pi. In addition, we try to calculate the area.
1 2 3 4 5 6 7 |
//Sample 03a: This throws Error CCircle(float rad) { pi = 3.14159; m_radius = rad; m_Area = pi * m_radius * m_radius; } |
When we compile the code, we get the Error C2758. Because we declare the member Pi as
const float pi;
. But, we try to assign a value in the constructor through assignment operator.

Compiler Error C2758
3. Error C2758 and Constructor Initializer List
The error in the past section showed that we should initialize the const members with the Constructor Initializer List. The picture below shows how one can define the Initializer List as part of the Constructor:

Constructor Initializer List
The above picture shows the syntax for Constructor Initializer List and it is executed first, before executing the very first statement in the constructor’s body. Now, we should adjust our constructor so that it loads the const Pi through the initializer list. The changed constructor is below:
1 2 3 4 |
//Sample 03b: Constructor with Initializer CCircle(float rad) : pi(3.14159), m_Area(pi * m_radius * m_radius), m_radius(rad) {} |
Note that the list is having three initialization split by a comma. We set the values to
pi, m_radius
. Also, we calculated the value for
m_Area
using this list. But, some people choose calculated values go inside the body of the constructor as it will use the already initialized member. The full example is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
//Example 01 #include "stdafx.h" #include <iostream> using namespace std; class CCircle { // Sample 01: Members of Triangle class private: const float pi; float m_radius; float m_Area; public: //Sample 02: Method retruning a Calculated Area float GetArea() { return m_Area; } ////Sample 03a: This throws Error //CCircle(float rad) //{ // pi = 3.14159; // m_radius = rad; // m_Area = pi * m_radius * m_radius; //} //Sample 03b: Constructor with Initializer CCircle(float rad) : pi(3.14159), m_Area(pi * m_radius * m_radius), m_radius(rad) {} }; int main() { //Sample 05: Creating the Circle object // with const member with it. CCircle objCircle(3); cout << endl; cout << "Area of Circle: " << objCircle.GetArea(); } |
The below picture shows the output of the example:

Constructor Initializer List Example 1
4. Setting Different Constant Data Per Object
In the previous example, we bind the const value 3.14159 to the constant data member Pi. Sometimes, each object needs its own const value. Say, for example, you are developing a Payroll processing application, which uses a class that represents a group of employees in the form of a department. Lets us say bonus for each department varies, but we apply the same bonus to all the employees within a department. Here, the bonus is a constant which is bound to a value when we create the object. Look at the example given below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
//Example 02 #include "stdafx.h" #include <iostream> using namespace std; class CEmployees { //Sample 01: Private members. private: float m_Emp1Salary; float m_Emp2Salary; float m_Emp3Salary; const float m_bunus_percent; public: //Sample 02: Constrctor Initializer List. See how //a constant value for m_bunus_percent is set here once. //It cannot be changes after this. CEmployees(float e1_sal, float e2_sal, float e3_sal, float PercentBonus): m_Emp1Salary(e1_sal), m_Emp2Salary(e2_sal),m_Emp3Salary(e3_sal), m_bunus_percent(PercentBonus) {} //Sample 02: Change Employee Salary void Change_Salary(int emp_no, float New_Salary) { if (emp_no == 1) m_Emp1Salary = New_Salary; if (emp_no == 2) m_Emp2Salary = New_Salary; if (emp_no == 3) m_Emp3Salary = New_Salary; } //Sample 03: Compute Bonus and Print void Print_SalaryandBonus() { cout << endl; cout << "Employee 1:" << endl; cout << "Salary = " << m_Emp1Salary << ", Bonus = " << m_Emp1Salary * m_bunus_percent / 100 << endl; cout << "Employee 2:" << endl; cout << "Salary = " << m_Emp2Salary << ", Bonus = " << m_Emp2Salary * m_bunus_percent / 100 << endl; cout << "Employee 3:" << endl; cout << "Salary = " << m_Emp3Salary << ", Bonus = " << m_Emp3Salary * m_bunus_percent / 100 << endl; cout << "==========================" << endl; cout << endl; } }; int main() { //Sample 04: Welding Deportment Employees CEmployees Welding_Emps(2000, 3000, 2500, 10); Welding_Emps.Print_SalaryandBonus(); //Sample 05: Lathe Dept Employees CEmployees Lathe_Emps(1000,3700, 2000, 5); Lathe_Emps.Change_Salary(1, 6000); Lathe_Emps.Print_SalaryandBonus(); } |
In the example, we declare the bonus as a constant like,
const float m_bunus_percent;
. But, the const is bound to a user-supplied value of
PercentBonus
. The below code shows the constructor initializer list:
1 2 3 4 5 6 |
//Sample 02: Constrctor Initializer List CEmployees(float e1_sal, float e2_sal, float e3_sal, float PercentBonus): m_Emp1Salary(e1_sal), m_Emp2Salary(e2_sal),m_Emp3Salary(e3_sal), m_bunus_percent(PercentBonus) {} |
Look at the below two statement. We have two
CEmployees
objects
Welding_Emps
and
Lathe_Emps
. But, these objects binds to different bonus percentage 10 and 5. The important thing about this is that we can not change constant objects after the binding. In our case, Welding Employees have bonus percentage of 10 and Lathe Workers have the bonus percentage of 5. This example also uses the constructor initializer list, and we require it as we have a constant member to hold the bonus percentage.
1 2 |
CEmployees Welding_Emps(2000, 3000, 2500, 10); CEmployees Lathe_Emps(1000,3700, 2000, 5); |
The below picture shows the output of this second example. In the output, you can see that the salary for the employee one is changed. However, we cannot change the bonus percentage.

Constructor Initializer List Example 2
5. Initializer List Order
The order of the constructor initializer list is not critical. Because C++ adheres to the order in which we lay the object in the class template. But, it is a best practice to keep the list to match with the data member layout of the class. In the below example, we have kept no order in the constructor initializer. This means, the order in the list does not match with the member variable layout of the class template
CGameCar
. The constructor initializer list is below:
1 2 3 4 5 6 7 8 9 10 |
//Sample 04: GameCar Class class CGameCar { private: CEngine m_engine; CTyres m_tyres; CGlass m_glass; public: CGameCar():m_glass(3),m_tyres(2), m_engine(3){} }; |
In the above example, one may think the initialization order is m_glass, m_tyres and m_engine. But the order is Engine, Tyres, and Glass. This is because C++ respects the Objects layout in the class template and not the order in the Constructor. The below code shows this:
1 2 3 4 |
private: CEngine m_engine; CTyres m_tyres; CGlass m_glass; |
The complete example is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
//Example 03 #include "stdafx.h" #include <iostream> using namespace std; //Sample 01: The Engine Class class CEngine { private: int m_x; public: CEngine(int x) { m_x = x; cout << "Engine Created" << endl; } }; //Sample 02: Tyres Class class CTyres { private: int m_x; public: CTyres(int x) { m_x = x; cout << "Tyres Created" << endl; } }; //Sample 03: Glass Class class CGlass { private: int m_x; public: CGlass(int x) { m_x = x; cout << "Front and Rear Glasses Created" << endl; } }; //Sample 04: GameCar Class class CGameCar { private: CEngine m_engine; CTyres m_tyres; CGlass m_glass; public: CGameCar():m_glass(3),m_tyres(2), m_engine(3){} }; //Sample 05: The Main method trying to create the GameCar class int main() { cout << endl; CGameCar car1; return 0; } |
Output:

Constructor Initializer List Example 3
So, again, the order is based on the Layout of the class template and not the order in which the Initializer List is formed. It will be a best practice to maintain the same order in the class Layout as well as in the Initializer List. This will help a user to know about the initialization order without looking the class Layout.
6. Summary
We saw that a Constructor Initializer List is good to give a value to the const data member. Then with an example, we saw how do we have different objects of the same class type having a different constant value. Finally, in this article examined the order of Initializer List does nothing but the layout of the class will. Note, we can initialize a reference member the same way as we did for constant.
Categories: C++
Tags: Constructor, Initializer List