Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use the initializer list or perform assignments in my C++ constructors?

class Node
{
public:

    Node *parent; // used during the search to record the parent of successor nodes
    Node *child; // used after the search for the application to view the search in reverse

    float g; // cost of this node + it's predecessors
    float h; // heuristic estimate of distance to goal
    float f; // sum of cumulative cost of predecessors and self and heuristic

    Node() :
            parent( 0 ),
            child( 0 ),
            g( 0.0f ),
            h( 0.0f ),
            f( 0.0f )
    {
    }

    UserState m_UserState;
};

Why we should use the constructor

    Node() :
            parent( 0 ),
            child( 0 ),
            g( 0.0f ),
            h( 0.0f ),
            f( 0.0f )
    {
    }

instead of

    Node()
    {
        parent = null;
        child = null;
        g = 0.0f;
        h = 0.0f;
        f = 0.0f;
    }

Thanks :)

like image 492
Dzung Nguyen Avatar asked Apr 19 '11 10:04

Dzung Nguyen


2 Answers

For plain old data (POD), this has little benefit, but once you start either using references or composing classes it makes a difference:

class Foo {
    Bar bar;

  public:
    // construct bar from x
    Foo(int x) : bar(x) { }
};

versus

Foo::Foo(int x)
{
    // bar is default-constructed; how do we "re-construct" it from x?
    bar = x;  // requires operator=(int) on bar; even if that's available,
              // time is wasted default-constructing bar
}

Sometimes, you won't even have a way of "re-constructing" an object once it has been constructed, as a class may not support setters or operator=. const members can certainly not be "re-constructed" or reset:

class FooWithConstBar {
    const Bar bar;

  public:
    Foo(int x) {
        // bar is cast in stone for the lifetime of this Foo object
    }
};

Edit: thanks to @Vitus for pointing out the problem with references.

like image 61
Fred Foo Avatar answered Oct 21 '22 14:10

Fred Foo


As there are some circumstances where you actually need or by performance reasons should initialize members using an initialization list, you should be consistent and always use it.

Examples where you need to use initialization lists is when an aggregate has no default constructor or when you have const members (yes, uncommon, but allowed).

An example where when you should (but aren't forced to) use initialization lists is when you have an aggregate object and the following points are valid:

  • The aggregate has a default constructor.
  • You need to setup the object with non-default values.
  • The aggregate has a constructor that allows you to set the desired non-default values.

Now then - why should you not use it?

like image 38
rjnilsson Avatar answered Oct 21 '22 14:10

rjnilsson