Wiki Markup |
---|
It is often recommended that class objects be initialized using direct constructors rather than assignment. \[[Meyers 01|AA. Bibliography#Meyers 01]\] Direct constructors avoids construction, copying, and destruction of a temporary copy of the object. To wit, object should be constructed this way: |
Code Block |
---|
|
Widget w( /* constructor arguments */);
|
rather than this way:
Code Block |
---|
|
Widget w = Widget( /* constructor arguments */);
|
or this way (for classes that support this syntax)
Code Block |
---|
|
Widget w = /* constructor argument */;
|
...
In this non-compliant example, the class Widget
has a default constructor.
Code Block |
---|
|
class Widget {
public:
explicit Widget() {cerr << "constructed" << endl;}
};
int main() {
Widget w();
return 0;
}
|
...
This situation is ameliorated by removing the parentheses after w
.
Code Block |
---|
|
class Widget {
public:
explicit Widget() {cerr << "constructed" << endl;}
};
int main() {
Widget w;
return 0;
}
|
...
Here is a more complex non-compliant example. The class Widget
maintains a single int
, and the class Gadget
maintains a single Widget
.
Code Block |
---|
|
class Widget {
public:
explicit Widget(int in) : i(in) {cerr << "widget constructed" << endl;}
private:
int i;
};
class Gadget {
public:
explicit Gadget(Widget wid) : w(wid) {cerr << "gadget constructed" << endl;}
private:
Widget w;
};
int main() {
int i = 3;
Gadget g(Widget(i));
cout << i << endl;
return 0;
}
|
The declaration of g
is not parsed as a Gadget
with a 1-argument constructor. It is instead parsed as a pointer to a function that takes a single Widget
argument, called i
, and returns a Gadget
. For illustrative purposes, keep in mind that in a function declaration, parentheses around argument names are optional. So the following is a legitimate function declaration, and indicates how the compiler sees the above declaration:
Code Block |
---|
|
Gadget g(Widget i);
|
As a result, this program compiles cleanly and prints only 3
as output, because no Gadget
or Widget
is constructed.
...
This situation is ameliorated by moving the Widget
construction outside Gadget
.
Code Block |
---|
|
int main() {
int i = 3;
Widget w(i);
Gadget g(w);
cout << i << endl;
return 0;
}
|
...