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 :)
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.
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?
Prefer initialization lists
Mainly because of performance issues.
It's discussed here.
The main reason is object validity and class invariants. Another reason is ease of use.
If you put everything in the constructor then when the constructor finishes you are guaranteed a valid Node. If you had to set all the instance variables separately then it would be possible to have a Node with some of the variables uninitialised either because the programmer forgot or if one of the assignments throws an exception. The latter would not occur in your case but in general it could. If the Node is not fully initialised its behaviour cannot be guaranteed to be as you expect.
精彩评论