A: Initialization lists or "initialization lists" are executed at the very beginning of the construction of an object, before the body of the constructor is entered. They are used to initialize the values in the object:

Code:

Foo::Foo(Bar bar) : bar(bar) {}

Taking the code sample above and removing the initialization list, we see another version of the Foo constructor that does the same thing with less efficiency:

Code:

Foo::Foo(Bar bar)
{
this->bar = bar;
}

The reason this version of the Foo constructor - which assigns a value to bar instead of initializing it - is inefficient is because the initialization list is still run implicitly (to call the default constructor of bar), regardless of whether one is supplied (Meyers 2007). This means that bar is (unnecessarily) assigned values twice:

Once run, you will notice that two Bar objects are constructed; the one created in main and the one in Foo's constructor:

Quote:

Bar constructed.
Bar default-constructed.

Now, if you change this

Code:

Foo::Foo(Bar bar)
{this->bar = bar;
}

to this

Code:

Foo::Foo(Bar bar) : bar(bar) {}

you will notice that only one Bar object is constructed; the one in main:

Quote:

Bar constructed.

Although it has been noted that the performance difference between the two versions is negligible when the data members are of an integral type (int, char, etc.), the initialization list is still preferred for consistency (Cline 2006)(Meyers 2007).

An example of the occasions where initialization lists cannot be used is in the initialization of arrays as data members.

Initialization lists are often written in different conventions that employ varying styles of indentation and spacing, which can result in confusion amongst beginners who have not seen the construct before. However, they are all semantically identical. Following are a few common variations:

Code:

Foo::Foo(Bar bar) : bar(bar) {}

Foo::Foo(Bar bar) : bar(bar)
{}

Foo::Foo(Bar bar) : bar(bar)
{
}

Foo::Foo(Bar bar)
: bar(bar) {}

Foo::Foo(Bar bar)
: bar(bar)
{}

Foo::Foo(Bar bar)
: bar(bar)
{
}

Q: Is there a situation when I must use the initialization list?

A: Yes. If you have constants or references in your class, they can only be initialized in the initialization list.

Code:

class foo
{
const int MAX_SIZE;
int& ref;

public:
foo(int& r):MAX_SIZE(128), ref(r) {}

// this is wrong
// foo() {MAX_SIZE = 128; ref = r; }
};

Q: Are there other cases when the initialization list is helpful?

A: Yes. For instance, if you have a constructor parameter with the same name with a field you want to assign it to, the compiler knows how to resolve correctly the names:

Code:

class foo
{
int data;

public:
foo(int data):data(data){}
};

The above is equivalent to:

Code:

class foo
{
int data;

public:
foo(int data)
{
this->data = data;
}
};

Q: Is the order of the objects in the initialization list important?

A: No. The objects are initialized in the order they are declared in the class. That is the only thing that matter.

Summarizing, you should prefer initialization lists to assigning data members values in the constructor body for efficiency and consistency.