2010-05-03

C++: Why initializer list?

class Parent;

class Child {
public:
    Child(
        Parent& parent_
        , const std::string& name_
        , const Color& eyeColor_
    )
    : parent(parent_)
    , name(name_)
    , eyeColor(eyeColor_)
    , money(0,"EUR")
    { }
    Parent& GetParent(){ return parent; }
    std::string GetName() const { return name; }
    Money GetMoney() const { return money; );
    Money AdjustMoney(int diff)
    { money += diff; return money; }
private:
    Parent &parent;
    const std::string name;
    Color eyeColor;
    Money money;
};
The initializer list in the above is this:
: parent(parent_)
, name(name_)
, eyeColor(eyeColor_)
, money(0,"EUR")
  • because of initializing references.

    References are like pointers with two restrictions. Firstly: You (if you are sane) point only to one object with a reference, you never point to an array. Secondly: Once the location is pointed you will not point elsewhere. This "finally" sounding behavior is perfectly good when we want to point one's (abstract) parent.

    If you want the language to force you to keep the second rule and still want your compiler in this millennium then you have to realize, that the initializer must be done before the begin ({) sign appears with it's endless possibilities.

  • because of initializing const members.

    Same as the above, but we are not talking about making up our mind early about a location but about a value. See the name member

  • because of initializing an aggregated object which do not have default constructor.

    Let's imagine the Color class which has only the copy constructor and that one: Color::Color(unsigned char r, unsigned char g, unsigned char b)! This class does not have default value / state by design, so it cannot be constructed without some instructions. See the eyeColor member.

  • because of speed

    You begin your program (constructor body) at the '{' sign. At that point all of your variables must be in a valid state. So if you give value to your members after that point you will waste processor time. One construction and one assignment, instead of simply one construction. See the money member.

    In most of my codes the constructors' body used to be empty. If we want to work in that style we will have to have handy constructors for our classes, which is not a bad thing at all.

Important: The execution of the initializer list is in the order of the data members because that order means the construction order and the reverse of that means the destruction order. If it wouldn't be like that then the program would have to remember the construction order and apply the reverse of it upon destruction. That would waste resources. So the rule came...

... and don't worry about hidden errors! Turn on the warnings in your compiler and take the advices and notes seriously! Seriously like Treat warnings as errors compiler option.

No comments:

Post a Comment