The answer is in understanding the difference between initialization and assignment. For some objects you don't have any option other than initializing the object in the initialization list.
First, the name object is not restricted to a class or struct. An object is any name. So, int value = 0; declares and initializes an object named value.
Anyways, here is the thing:
An object needs to be initialized in the initialization list when it either doesn't provide a default constructor or it is a const object. Lets go back to my first paragraph and work with a const object to better understand the difference.
Const objects cannot be changed. An implication of this rule is that they must be initialized when they are defined.
Code:
const int value = 12; // correct.
const int val; // compile-time error. const objects need to be initialized
value = 23; // compile-time error. Attempting to assign to a const object
You initialize an object when you first assign to an object. You don't initialize an object on any subsequent assignment.
Code:
int value = 12; // object defined and initialized
int val; // object defined but uninitialized (see below)
value = 23; // object assignment. Not initialization
val = 13; // object initialized.
There is an important distinction for objects of built-in type, like the ones above, when defined on the global scope. The val object above is assumed to have been defined on the local scope (inside main() or any other function). Objects of built-in type defined in the global scope are usually zero-initialized. "Usually", because it depends on your compiler. So, had val been defined outside main(), it would have been in fact initialized to 0. The expression val = 13; you see after that would then have been an assignment, not a initialization.
For the most part this distinction between assigment and initialization is not important. But it becomes so when working with classes and initialization lists.
The initialization list in a class constructor declaration, like the name itself implies, initializes the class members. The body of the constructor, on the other hand, assigns to them.
Code:
// Correct. const_val and val initialized
class MyClass {
public:
MyClass(int x, int y): const_val(x), val(y) {}
void get_data() { std::cout << const_val << " " << val << std::endl; }
private:
const int const_val;
int val;
};
// Correct const_val initialized and Non const of built-in type assigned.
class MyClass {
public:
MyClass(int x, int y): const_val(x) { val = y; }
void get_data() { std::cout << const_val << " " << val << std::endl; }
private:
const int const_val;
int val;
};
//Compile-time error. Attempting to assign to const_val.
class MyClass {
public:
MyClass(int x, int y): val(y) { const_val = x}
void get_data() { std::cout << const_val << " " << val << std::endl; }
private:
const int const_val;
int val;
};
And that's about it. If an object that doesn't define a default constructor is made a data member of another class, it must also be initialized in the initialization list.
Code:
class SomeObject {
public:
SomeObject(int x): value(x) {} // non-default constructor
private:
int value;
};
class UsingSomeObject {
public:
UsingSomeObject(SomeObject obj) { value = obj; } // Compile-time error.
private:
SomeObject value;
};