Initializer List in C++

Initializer list is used to initialize data members. The syntax begins with a colon(:) and then each variable along with its value separated by a comma. The initializer list does not end in a semicolon.

Syntax:

Constructorname(datatype value1, datatype value2):datamember(value1),datamember(value2)
{
    ...
}

For example:

#include<iostream>
using namespace std;

class Base
{
    private:
    int value;
    public:
    // default constructor
    Base(int value):value(value)
    {
        cout << "Value is " << value;
    }
};

int main()
{
    Base il(10);
    return 0;
}

Value is 10

The above code is just an example to understand the syntax of Initializer list. In the above code, value can easily be initialized inside the constructor as well, hence we do not have to use initializer list.


Uses of Initializer List in C++

There are situations where initialization of data members inside constructor doesn't work and Initializer List must be used. Following are such cases:


1) When no Base class default constructor is present

In Inheritance base class constructor is called first(Order of Constructor call), followed by the child class constructor.

Therefore, in the example below Base_ class constructor will be called before InitilizerList_ class constructor due to which the below program will throw compilation error: "No default constructor exists for class Base_".

#include<iostream>
using namespace std;

class Base_
{
    public:
    // parameterized constructor
    Base_(int x)
    {
        cout << "Base Class Constructor. Value is: " << x << endl;
    }
};

class InitilizerList_:public Base_
{
    public:
    // default constructor
    InitilizerList_()
    {
        Base_ b(10);
        cout << "InitilizerList_'s Constructor" << endl;
    }
};

int main()
{
    InitilizerList_ il;
    return 0;
}

The above code example can be rewritten using initializer list, and will execute smoothly without any error.

Here is the new code:

#include<iostream>
using namespace std;

class Base_
{
    public:
    // parameterized constructor
    Base_(int x)
    {
        cout << "Base Class Constructor. Value is: " << x << endl;
    }
};

class InitilizerList_:public Base_
{
    public:
    // default constructor using initializer list
    InitilizerList_():Base_(10)
    {
        cout << "InitilizerList_'s Constructor" << endl;
    }
};

int main()
{
    InitilizerList_ il;
    return 0;
}

Base Class Constructor value is 10 InitilizerList_'s constructor




2) When reference type is used

If you have a data member as reference type, you must initialize it in the initialization list. References are immutable hence they can be initialized only once.

#include<iostream>
using namespace std;

class Base
{
    private:
    int &ref;
    public:
    Base(int &ref):ref(ref)
    {
        cout << "Value is " << ref;
    }
};

int main()
{
    int ref=10;
    Base il(ref);
    return 0;
}

Value is 10


3) For initializing const data member

const data members can be initialized only once, so it must be initialized in the initialization list.

#include<iostream>
using namespace std;

class Base
{
    private:
    const int c_var;
    public:
    Base(int c_var):c_var(c_var)
    {
        cout << "Value is " << c_var;
    }
};

int main()
{
    Base il(10);
}

Value is 10


4) When data member and parameter have same name

#include<iostream>
using namespace std;

class Base
{
    private:
    int value;
    public:
    Base(int value):value(value)
    {
        cout << "Value is " << value;
    }
};

int main()
{
    Base il(10);
    return 0;
}

Value is 10


5) For improving performance

If you are assigning the values inside the body of the constructor, then a temporary object would be created which will be provided to the assignment operator. The temporary object will be destroyed at the end of the assignment statement. Creation of temporary object can be avoided by using initializer list.