Introduction:
The data members of a class are initialized using an initializer list . The constructor specifies the initialization list of members as a comma-separated list followed by a colon. Here is an illustration of how to initialize the x and y properties of the Point class using the initializer list .
#include<iostream>
using namespace std;
class Point {
private:
int x;
int y;
public:
Point(int i = 0, int j = 0):x(i), y(j) {}
/* The above use of Initializer list is optional as the
constructor can also be written as:
Point(int i = 0, int j = 0) {
x = i;
y = j;
}
*/
int getX() const {return x;}
int getY() const {return y;}
};
int main() {
Point t1(11, 17);
cout<<"x = "<<t1.getX()<<", ";
cout<<"y = "<<t1.getY();
return 0;
}
Output:
x = 11, y = 17
Explanation:
The code shown above only serves as an illustration of the Initializer list's syntax . In the code above, initializing x and y in the constructor is also a simple process. However, there are some circumstances when using an initializer list instead of initializing data members inside the constructor is necessary. These instances are as follows:
1) For non-static const data members initialization:
Const data members require the use of an Initializer List to be initialized. In the example below, "t" is an initializer list -initialized const data member of the Test class. Const data members are initialized in the initializer list because no memory is allocated specifically for them; instead, they are folded into the symbol table , necessitating their initialization in the initializer list .
Additionally, because it is a parameterized constructor, we do not need to call the assignment operator, which saves us from doing an additional action.
#include<iostream>
using namespace std;
class Test {
const int t;
public:
Test(int t):t(t) {} //Here initializer is used
int getT() { return t; }
};
int main() {
Test t1(13);
cout<<t1.getT();
return 0;
}
Output:
2) For the reference members' initialization:
Initializer List must be used to initialize reference members. In the example that follows, "t" is an initializer list that initialized reference members of the Test class.
// initialization of the members of reference data
#include<iostream>
using namespace std;
class Test {
int &t;
public:
Test(int &t):t(t) {} //Use of an initializer list is required.
int getT() { return t; }
};
int main() {
int x = 50;
Test t1(x);
cout<<t1.getT()<<endl;
x = 60;
cout<<t1.getT()<<endl;
return 0;
}
Output:
50
60
3) For member objects that do not have a default constructor to be initialised:
As shown in the example below, class "A" does not have a default constructor , and object "a" of class "A" is a data member of class "B" . It is necessary to initialize "a" with an initializer list.
#include <iostream>
using namespace std;
class A {
int i;
public:
A(int );
};
A::A(int arg) {
i = arg;
cout << " Constructor A is called: Value of i: " << i << endl;
}
// Class B contains object of A
class B {
A a;
public:
B(int );
};
B::B(int x):a(x) { //Initializer list must be used
cout << " Constructor B is called";
}
int main() {
B obj(50);
return 0;
}
Output:
Constructor A is called: Value of i: 50
Constructor B is called
Explanation:
Initializer List is not required if we want to initialize "a" using the default constructor, but it is required if we want to initialize "a" using the parameterized constructor if class A has both default and parameterized constructors .
4) For base class member initialization:
Similar to point 3, only Initializer List can be used to call the base class' parameterized constructor .
#include <iostream>
using namespace std;
class A {
int i;
public:
A(int );
};
A::A(int arg) {
i = arg;
cout << "Constructor A is called: Value of i: " << i << endl;
}
// Class B is derived from A
class B: A {
public:
B(int );
};
B::B(int x):A(x) { //Initializer list must be used
cout << "Constructor B is called";
}
int main() {
B obj(46);
return 0;
}
Output:
Constructor A is called: Value of i: 46
Constructor B is called
5) When a data member's name is the same as a constructor parameter
If the name of the constructor argument and the name of the data member match, then either this pointer or the Initializer List must be used to initialize the data member. The member name and parameter name for A in the example below are both "i" .
#include <iostream>
using namespace std;
class A {
int i;
public:
A(int );
int getI() const { return i; }
};
A::A(int i):i(i) { } // This pointer or the initializer list must be used.
/* The constructor described above can alternatively be written as
A::A(int i) {
this->i = i;
}
*/
int main() {
A a(45);
cout<<a.getI();
return 0;
}
Output:
6) For purposes of performance:
Instead of assigning values inside the body, it is preferable to initialize all class variables in the Initializer List . Think about the following instance:
// absence of initializer list
class MyClass {
Type variable;
public:
MyClass(Type a) { //Assume Type is a class that has previously been declared and has the necessary constructors and operators.
variable = a;
}
};
The following steps are used by the compiler to generate an object of the MyClass type here.
The constructor of the type is first invoked for "a" .
"variable" is the default construct.
The MyClass constructor calls the assignment operator of "Type" to assign.
Variable a;
The processes that the compiler takes while dealing with the Initializer List are as follows:
- First, "a" is passed to the constructor of the type.
- The "Type" class's parameterized constructor is used to initialize a variable(a) . Direct copying of the construct "variable" is accomplished using the arguments in the initializer list .
- Since "a" exits the scope of "Type" , the destructor of "Type" is invoked. This example demonstrates how using assignment inside the constructor body results in three function calls: constructor, destructor , and one call for the addition assignment operator . Additionally, there are just two function calls when using an Initializer List: a copy constructor call and a destructor call .
- Finally, since "a" is no longer within the scope of "Type" , the destructor of "Type" is invoked.
Consider the same code modified to include the Initializer List in the MyClass constructor .
// With Initializer List
class MyClass {
Type variable;
public:
MyClass(Type a):variable(a) { // Assume Type is a class that has previously been declared and has the necessary constructors and operators.
}
};