Thread: Constructor Initialization

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    13

    Constructor Initialization

    Hi,
    Im currently reading a book and its trying to explain why i should use a constructor initialization list. However im not really understanding what its trying to say.

    Could anyone please give me an example of what this is trying to explain and what it means?

    Some variables cannot be initialized with ordinary assignment statements. As a somewhat recursive example, suppose that one of the member variables in your class is an object from some other class. This object should be initialized with a constructor, not a separate function such as init(), so you don’t even have the option of initializing by calling a member function.
    Thanks Alot
    Kane

  2. #2
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Code:
    class A {
    public:
        // this class has no default constructor
        A(int x) { val = x; }
    private:
        int val;
    };
    
    class B {
    public:
       // B() {} // error class A has no default constructor
       B():an_a(0) {} // this is ok
    private:
       A an_a;
    };
    
    int main() {
    }
    Kurt

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    The point is that class members are constructed before the constructor body is entered.

    Code:
    class A
    {
        int a , b;
        public:
        A(int x, int y)
            //x and y are constructed here
        {
            a = x; b = y; //just assignments
        }
    };
    Now, the above works without an initializer list.

    Let's suppose however, that we have a class that contains an instance of another class, which does not have a default constructor (i.e cannot be constructed without arguments).
    What happens is that the member object (A) needs to be created before entering the constructor body of ContainsA, but the compiler cannot call the constructor of this object, if you don't give it the arguments. That you can only do in the initializer list.

    Try out the next program. Comment out the initializer list of ContainsA, and see if you can still somehow make this code compile without modifying A.

    Code:
    #include <iostream>
    
    class A
    {
        int a, b;
        public:
            A(int x, int y)
            {
                a = x;
                b = y;
            }
            void print() const
            {
                std::cout << a << ", " << b;
            }
    };
    
    class ContainsA
    {
        A a;
        int c;
        public:
            ContainsA(int x, int y, int z)
    //This wouldn't work without an initializer, because here member "a" has to be constructed
    //but no default constructor has been provided.
    //Hence:
            : a(x, y) //Try without this and see that it doesn't compile
            {
                c = z; //could be done in initializer too
            }
            void print() const
            {
                a.print();
                std::cout << ", " << c << '\n';
            }
    };
    
    int main()
    {
        ContainsA test(1, 2, 3);
        test.print();
        std::cin.get();
    }
    Another situation where you absolutely need to use the initialization list, is if the class contains const members. Those can only be initialized where they are created, and that happens before the opening brace.

    In general: use initializer lists whenever you can. They are more efficient, very readable and easy to type
    Last edited by anon; 04-05-2007 at 04:39 AM.

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    13
    thanks for the replies.

    what i dont quite understand is why the constructor for A isnt called when you create and object of it (A a;)?
    And if its called at the initialization stage of the constructor for ContainsA, shouldnt it be created here as well like A a(x, y) ?

    eg
    Code:
    public:
            ContainsA(int x, int y, int z)
             : A a(x, y) 
            {

  5. #5
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by Kane View Post
    what i dont quite understand is why the constructor for A isnt called when you create and object of it (A a;)?]
    A has no constructor that has no parameters -> A a; is illegal

    And if its called at the initialization stage of the constructor for ContainsA, shouldnt it be created here as well like A a(x, y) ?
    The langage designers have chosen differently. Think that makes sense. In the body of the class it's already defined that a is an A so why tell again.
    Kurt

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Quote Originally Posted by Kane View Post
    thanks for the replies.

    what i dont quite understand is why the constructor for A isnt called when you create and object of it (A a?
    And if its called at the initialization stage of the constructor for ContainsA, shouldnt it be created here as well like A a(x, y) ?

    eg
    Code:
    public:
            ContainsA(int x, int y, int z)
             : A a(x, y) 
            {
    You have already declared A a in the class declarations. Now you need to initialize it or make the declared object alive, but without using assignment, which always presupposes that the object you are assigning to is already valid and constructed.

    That's the way the language has been designed.

    You can also think about it so: the class declaration (where A a; is declared) is not code that does something or is executed. Now, when we create an instance of this class, where would the members actually be initialized?

    In the constructor, and more precisely, before the code in the constructor body is executed. In the constructor body you can assume that this object is already fully created and now you can write code for whatever else you want to happen in the constructing phase.

    Dealing with "half"-objects would introduce lots of problems. There-fore in C++, you never get your hands on a half-constructed object (with the exception of contructor initializers, where you need to pay attention to the order you are initializing members, and with inheritance in a different sense). If you don't specify how to construct an object, the compiler does it for you. If this wasn't done implicitly for you (if you don't use initializers), that would mean that you could end up with half-valid objects (e.g an object of ContainsA, where A actually doesn't exist, because you forgot to construct it.)


    Now, you can mess up as a programmer (for example forget to initialize members of built-in types, which will then contain garbage values), but as far as the language itself is concerned, if you create an object of a class, it is guaranteed that all the parts of the class actually exist.

Popular pages Recent additions subscribe to a feed