CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 1 of 1
  1. #1
    Join Date
    Nov 2006
    Location
    Australia
    Posts
    1,569

    C++ General: What is the initialization list and why should I use it?

    Q: What are initialization lists in C++ and why should I use them?

    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 in the initialization list
    • Once in the constructor body
    To demonstrate this, compile and execute this code:
    Code:
    #include 
    
    class Bar
    {
    public:
      Bar();
      Bar(int x);
    private:
      int x;
    };
    
    Bar::Bar()
    {
      std::cout << "Bar default-constructed." << std::endl;
    }
    
    Bar::Bar(int x) : x(x)
    {
      std::cout << "Bar constructed." << std::endl;
    }
    
    class Foo
    {
    public:
      Foo(Bar bar);
    private:
      Bar bar;
    };
    
    Foo::Foo(Bar bar)
    {
      this->bar = bar;
    }
    
    int main()
    {
        Foo foo(Bar(3));
    
        return 0;
    }
    Once run, you will notice that two Bar objects are constructed; the one created in main and the one in Foo's constructor:
    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:
    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.

    Cline, M. (2006). "C++ FAQ Lite: [10] Constructors." Retrieved 28th October, 2008, from http://www.parashift.com/c++-faq-lit....html#faq-10.6.
    Meyers, S. (2007). Effective C++. Westford, Massachusetts, Addison-Wesley.
    Last edited by cilu; November 1st, 2008 at 06:11 AM. Reason: added more Q&As
    Good judgment is gained from experience. Experience is gained from bad judgment.
    Cosy Little Game | SDL | GM script | VLD | Syntax Hlt | Can you help me with my homework assignment?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured