Possible Duplicate:
Initializing fields in constructor - initializer list vs constructor body
In a lecture I attended, the lecturer talked briefly in C++ about non-default class constructors. He stated specifically that one version was preferable to the other. He showed these two examples:
Point::Point(double x, double y, double z)
: x_(x), y_(y), z_(z)
{}
Point::Point(double x, double y, double z)
{ x_= x; y_= y; z_= z; }
He mentioned that the first example (using parentheses) was the preferred way to write the constructor.
My question is: What's the difference and why does it matter? In what way is the first superior to the second?
The reason is that the first is not an assignment, it’s an initialisation, and the second code is actually identical to this:
Point::Point(double x, double y, double z)
: x_(), y_(), z_()
{ x_= x; y_= y; z_= z; }
That is, all members are default-initialised here before being assigned. That doesn’t work when their types have no default constructor. For instance:
class Foo {
Foo(); // Private, undefined constructor
public:
Foo(int) { }
};
class Bar {
int& i;
Foo f;
public:
Bar() { i = 0; f = Foo(0); }
};
This code won’t work because Bar
’s constructor relies on the existence of a default constructor for f
and an initialiser for i
, neither of which exists.
But even if all members are default-constructible or initialisable, it is still advisable to initialise them in the initialisation list rather than via assignment in the constructor: if nothing else, it’s more efficient (because otherwise you’ll perform redundant operations which may be costly in some cases).
The first copy-constructs the members prior to the constructor body being entered. Note: This is part of the larger subject of what is called a constructor initializer list in C++. It is mandatory for certain member variable types to be represented in the initializer list, among them reference members, members that have non-default construction (i.e. require parameters for their constructors), and const members. The usage in the case presented in the question is to invoke copy-constuction, as opposed to default-construction followed by in-body assignment, which brings us to...
The second default-constructs the members prior to the constructor body being entered, then assigns their values within the body. This is only viable for members that support default construction.
Of the two, the first is generally preferred, especially for complex data types that have expensive default-initialization. Said-initialization will likely be partially or completely wasted because of the ensuing assignment that is about to take place. You're generally better off foregoing that and using copy-construction instead. Note: All intrinsic data types (int
, float
, pointers, etc) support copy-constuction.
The second way performs a default construction, then an assignment.
If a default constructor isn't available it won't work, and either way it might not be as cheap.
Also, the first method can call an explicit constructor while the second one doesn't.