Initializing private member variables of a class

AnotherClass class2; creates another local object inside the constructor body, that gets destroyed at the end of the body. That is not how class members are initialized.

Class members are initialized before the constructor body in the member initializer list between the constructor signature and body, starting with a :, like so:

ClassName::ClassName() :
    class2(argumentsToPassToClass2Constructor),
    anotherMember(42) // just for example
{
    /* constructor body, usually empty */
}

If you don't want to pass any arguments to the class2 constructor you don't have to put it in the initializer list. Then its default constructor will be called.

If you simply want to call the default constructor on all of your class members, you can (and should) omit the constructor altogether. The implicitly generated default constructor will do just what you wanted.


What you are doing in your constructor is creating another variable, local only inside the constructor.

Actually, if you do nothing, the default constructor in AnotherClass will be called for the class2 object.

If you want to be explicit, you can use a constructor initializer list:

ClassName::ClassName()
    : class2()
{
}

This last method is also the way you call a specific constructor with arguments in AnotherClass, if you need to do that.


ClassName::ClassName() {
    AnotherClass class2; // this will create local variable only
}

If AnotherClass will have default constructor, then it will be called for the class2 object by compiler.

If you want to call parametrized constructor then you will have do it in following way:

ClassName::ClassName() :
    class2(arguments)

Why to use and How to use initializer list :

Consider the following example:

// Without Initializer List
class MyClass {
    Type variable;
public:
    MyClass(Type a) {  // Assume that Type is an already
                     // declared class and it has appropriate 
                     // constructors and operators
      variable = a;
    }
};

Here compiler follows following steps to create an object of type MyClass

  1. Type’s constructor is called first for “a”.
  2. The assignment operator of “Type” is called inside body of MyClass() constructor to assign

    variable = a;

  3. And then finally destructor of “Type” is called for “a” since it goes out of scope.

Now consider the same code with MyClass() constructor with Initializer List

// With Initializer List
class MyClass {
    Type variable;
public:
    MyClass(Type a):variable(a) {   // Assume that Type is an already
                     // declared class and it has appropriate
                     // constructors and operators
    }
};

With the Initializer List, following steps are followed by compiler:

  1. Copy constructor of “Type” class is called to initialize : variable(a). The arguments in initializer list are used to copy construct “variable” directly.
  2. Destructor of “Type” is called for “a” since it goes out of scope.

As we can see from this example if we use assignment inside constructor body there are three function calls: constructor + destructor + one addition assignment operator call. And if we use Initializer List there are only two function calls: copy constructor + destructor call.

This assignment penalty will be much more in “real” applications where there will be many such variables.

Few more scenarios, where you will have to use initializer list only:

  1. Parametrized constructor of base class can only be called using Initializer List.
  2. For initialization of reference members
  3. For initialization of non-static const data members