FAQs in section [10]:
[10.1] What's the deal with constructors?
Constructors build objects from dust.
Constructors are like "init functions". They turn a pile of arbitrary bits
into a living object. Minimally they initialize internally used fields. They
may also allocate resources (memory, files, semaphores, sockets, etc).
"ctor" is a typical abbreviation for constructor.
[ Top | Bottom | Previous section | Next section ]
[10.2] Is there any difference between List x; and List x();?
A big difference!
Suppose that List is the name of some class. Then function f() declares
a local List object called x:
void f()
{
List x; // Local object named x (of class List)
// ...
}
But function g() declares a function called x() that returns a
List:
void g()
{
List x(); // Function named x (that returns a List)
// ...
}
[ Top | Bottom | Previous section | Next section ]
[10.3] How can I make a constructor call another constructor as a
primitive?
No way.
Dragons be here: if you call another constructor, the compiler initializes a
temporary local object; it does not initialize this object. You can
combine both constructors by using a default parameter, or you can share their
common code in a private init() member function.
[ Top | Bottom | Previous section | Next section ]
[10.4] Is the default constructor for Fred always
Fred::Fred()?
No. A "default constructor" is a constructor that can be called with
no arguments. Thus a constructor that takes no arguments is certainly a
default constructor:
class Fred {
public:
Fred(); // Default constructor: can be called with no args
// ...
};
However it is possible (and even likely) that a default constructor can take
arguments, provided they are given default values:
class Fred {
public:
Fred(int i=3, int j=5); // Default constructor: can be called with no args
// ...
};
[ Top | Bottom | Previous section | Next section ]
[10.5] Which constructor gets called when I create an
array of Fred objects? 
[Recently changed so it uses new-style headers and the std:: syntax and reworded references to STL (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
Fred's default constructor (except as discussed
below).
There is no way to tell the compiler to call a different constructor (except as
discussed below). If your class Fred doesn't have a default constructor, attempting to create an array of Fred objects is
trapped as an error at compile time.
class Fred {
public:
Fred(int i, int j);
// ... assume there is no default constructor in class Fred ...
};
int main()
{
Fred a[10]; // ERROR: Fred doesn't have a default constructor
Fred* p = new Fred[10]; // ERROR: Fred doesn't have a default constructor
}
However if you are constructing an object of the standard
std::vector<Fred> rather than an array of Fred (which you probably should
be doing anyway since arrays are evil), you don't
have to have a default constructor in class Fred, since you can give the
std::vector a Fred object to be used to initialize the elements:
#include <vector>
int main()
{
std::vector<Fred> a(10, Fred(5,7));
// The 10 Fred objects in std::vector a will be initialized with Fred(5,7).
// ...
}
Even though you ought to use a std::vector rather than an array,
there are times when an array might be the right thing to do, and for those,
there is the "explicit initialization of arrays" syntax. Here's how it looks:
class Fred {
public:
Fred(int i, int j);
// ... assume there is no default constructor in class Fred ...
};
int main()
{
Fred a[10] = {
Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7),
Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7)
};
// The 10 Fred objects in array a will be initialized with Fred(5,7).
// ...
}
Of course you don't have to do Fred(5,7) for every entry you can put
in any numbers you want, even parameters or other variables. The point is that
this syntax is (a) doable but (b) not as nice as the std::vector syntax. Remember
this: arrays are evil unless there is a
compelling reason to use an array, use a std::vector instead.
[ Top | Bottom | Previous section | Next section ]
[10.6] Should my constructors use "initialization lists" or "assignment"?
Constructors should initialize all member objects in the initialization list.
For example, this constructor initializes member object x_ using an
initialization list: Fred::Fred() : x_(whatever) { }.
From a performance perspective, it is important to note that the
whatever expression doesn't automatically cause a separate object to be
created and copied into x_: if the types are the same the result of
...whatever... will be constructed directly inside x_.
In contrast the following constructor uses assignment: Fred::Fred() { x_ = whatever; }. In this case the
expression whatever causes a separate, temporary object to be created,
and this temporary object is passed into the x_ object's assignment
operator, then is destructed at the ;. That's inefficient.
There's another source of inefficiency as well: in the second (assignment)
case, the object's default constructor (implicitly called before the
constructor body's "{") might, for example, allocate some default
amount of memory or open some default file. All this work could be for naught
if the whatever expression and/or assignment operator causes the object
to close that file and/or release that memory (e.g., if the default constructor
didn't allocate a large enough pool of memory or if it opened the wrong file).
Conclusion: All other things being equal, your code will run faster if you use
initialization lists rather than assignment.
[ Top | Bottom | Previous section | Next section ]
[10.7] Should you use the this pointer in the constructor?
Some people feel you should not use the this pointer in a constructor because
the this object is not fully formed yet. However you can use this in the
constructor (in the {body} and even in the initialization list) if you are careful.
Once you're in the {body} of the constructor, it's easy to
imagine that you can use the this pointer since all the base class subobjects
and the member objects will already have been fully constructed. However even
there you must be careful. For example, if you call a virtual member
function (or call some other function which turns around and calls a virtual
member function) on the this object, you
may not get what you want.
But you are even allowed to use the this pointer in the constructor's
initializer list, provided you are very careful that you
don't touch any member objects or base class subobjects that have not yet been
constructed. This requires a rather intimate knowledge of the order that
things happen in a constructor you have been warned. The safest thing to do
is store the value of the this pointer somewhere and use that pointer later.
[ Top | Bottom | Previous section | Next section ]
[10.8] What is the "Named Constructor Idiom"? 
[Recently fixed a typo (Fred vs. Point) in the prose thanks to Roy LeCates (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
A technique that provides more intuitive and/or safer construction operations
for users of your class.
The problem is that constructors always have the same name as the class.
Therefore the only way to differentiate between the various constructors of a
class is by the parameter list. But if there are lots of constructors, the
differences between the constructors becomes somewhat subtle and error prone.
With the Named Constructor Idiom, you declare all the class's constructors in
the private: or protected: sections, and you provide public static
methods that return an object. These static methods are the so-called "Named
Constructors." In general there is one such static method for each different
way to construct an object.
For example, suppose we are building a Point class that represents a position
on the X-Y plane. Turns out there are two common ways to specify a 2-space
coordinate: rectangular coordinates (X+Y), polar coordinates (Radius+Angle).
(Don't worry if you can't remember these; the point isn't the particulars of
coordinate systems; the point is that there are several ways to create a
Point object). Unfortunately the parameters for these two coordinate systems
are the same: two floats. This would create an ambiguity error in the
overloaded constructors:
class Point {
public:
Point(float x, float y); // Rectangular coordinates
Point(float r, float a); // Polar coordinates (radius and angle)
// ERROR: Overload is Ambiguous: Point::Point(float,float)
};
int main()
{
Point p = Point(5.7, 1.2); // Ambiguous: Which coordinate system?
}
One way to solve this ambiguity is to use the Named Constructor Idiom:
#include <cmath> // To get sin() and cos()
class Point {
public:
static Point rectangular(float x, float y); // Rectangular coord's
static Point polar(float radius, float angle); // Polar coordinates
// These static methods are the so-called "named constructors"
// ...
private:
Point(float x, float y); // Rectangular coordinates
float x_, y_;
};
inline Point::Point(float x, float y)
: x_(x), y_(y) { }
inline Point Point::rectangular(float x, float y)
{ return Point(x, y); }
inline Point Point::polar(float radius, float angle)
{ return Point(radius*cos(angle), radius*sin(angle)); }
Now the users of Point have a clear and unambiguous syntax for creating
Points in either coordinate system:
int main()
{
Point p1 = Point::rectangular(5.7, 1.2); // Obviously rectangular
Point p2 = Point::polar(5.7, 1.2); // Obviously polar
}
Make sure your constructors are in the protected: section if you expect
Point to have derived classes.
The Named Constructor Idiom can also be used to make sure your objects are always created via new.
[ Top | Bottom | Previous section | Next section ]
[10.9] Why can't I initialize my static member
data in my constructor's initialization list?
Because you must explicitly define your class's static data
members.
Fred.h:
class Fred {
public:
Fred();
// ...
private:
int i_;
static int j_;
};
Fred.cpp (or Fred.C or whatever):
Fred::Fred()
: i_(10) // OK: you can (and should) initialize member data this way
j_(42) // Error: you cannot initialize static member data like this
{
// ...
}
// You must define static data members this way:
int Fred::j_ = 42;
[ Top | Bottom | Previous section | Next section ]
[10.10] Why are classes with static data members
getting linker errors?
Because static data members must be
explicitly defined in exactly one compilation unit. If you didn't do
this, you'll probably get an "undefined external" linker error. For
example:
// Fred.h
class Fred {
public:
// ...
private:
static int j_; // Declares static data member Fred::j_
// ...
};
The linker will holler at you ("Fred::j_ is not defined") unless you
define (as opposed to merely declare) Fred::j_ in (exactly) one of your
source files:
// Fred.cpp
#include "Fred.h"
int Fred::j_ = some_expression_evaluating_to_an_int;
// Alternatively, if you wish to use the implicit 0 value for static ints:
// int Fred::j_;
The usual place to define static data members of class Fred is file
Fred.cpp (or Fred.C or whatever source file extension you use).
[ Top | Bottom | Previous section | Next section ]
[10.11] What's the "static initialization order fiasco"?
A subtle way to kill your project.
The static initialization order fiasco is a very subtle and commonly
misunderstood aspect of C++. Unfortunately it's very hard to detect the
errors occur before main() begins.
In short, suppose you have two static objects x and y which exist in
separate source files, say x.cpp and y.cpp. Suppose further
that the constructor for the y object calls some method on the x object.
That's it. It's that simple.
The tragedy is that you have a 50%-50% chance of dying. If the compilation
unit for x.cpp happens to get initialized first, all is well. But if
the compilation unit for y.cpp get initialized first, then y's
constructor will get run before x's constructor, and you're toast. I.e.,
y's constructor will call a method on the x object, yet the x object
hasn't yet been constructed.
I hear they're hiring down at McDonalds. Enjoy your new job flipping burgers.
If you think it's "exciting" to play Russian Roulette with live rounds in half the
chambers, you can stop reading here. On the other hand if you like to improve
your chances of survival by preventing disasters in a systematic way, you
probably want to read the next FAQ.
Note: The static initialization order fiasco does not apply to
builtin/intrinsic types like int or char*. For example if you create a
static float object, there is never a problem with static initialization
order. The only time the static initialization order is truly a fiasco
is when your static or global objects have a constructor.
[ Top | Bottom | Previous section | Next section ]
[10.12] How do I prevent the "static
initialization order fiasco"?
Use the "construct on first use" idiom, which simply means to wrap your
static object inside a function.
For example, suppose you have two classes, Fred and Barney.
There is a global Fred object called x, and a global Barney
object called y. Barney's constructor invokes the
goBowling() method on the x object. The file x.cpp defines
the x object:
// File x.cpp
#include "Fred.hpp"
Fred x;
The file y.cpp defines the y object:
// File y.cpp
#include "Barney.hpp"
Barney y;
For completeness the Barney constructor might look something like this:
// File Barney.cpp
#include "Barney.hpp"
Barney::Barney()
{
// ...
x.goBowling();
// ...
}
As described above, the disaster occurs if y is
constructed before x, which happens 50% of the time since they're in
different source files.
There are many solutions to this problem, but a very simple and completely
portable solution is to replace the global Fred object, x, with a
global function, x(), that returns the Fred object by reference.
// File x.cpp
#include "Fred.hpp"
Fred& x()
{
static Fred* ans = new Fred();
return *ans;
}
Since static local objects are constructed the first time control flows over
their declaration (only), the above new Fred() statement will only
happen once: the first time x() is called. Every subsequent call will return
the same Fred object (the one pointed to by ans). Then all you
do is change your usages of x to x():
// File Barney.cpp
#include "Barney.hpp"
Barney::Barney()
{
// ...
x().goBowling();
// ...
}
This is called the Construct On First Use Idiom because it does just
that: the global Fred object is constructed on its first use.
The downside of this approach is that the Fred object is never
destructed. The C++ FAQ Book has a second technique that answers this
concern (but at the cost of opening a "static de-initialization order
fiasco").
Note: You don't have to do this for builtin/intrinsic types like int or
char*. For example if you create a static or global float object, there
is no need to wrap it within a function. The only time the static
initialization order is truly a fiasco is when your static or global
objects have a constructor.
[ Top | Bottom | Previous section | Next section ]
[10.13] How do I prevent the "static
initialization order fiasco" for my static data members?
Just use the same technique just
described, but this time use a static member function rather than a
global function.
Suppose you have a class X that has a static Fred object:
// File X.hpp
class X {
public:
// ...
private:
static Fred x_;
};
Naturally this static member is initialized separately:
// File X.cpp
#include "X.hpp"
Fred X::x_;
Naturally also the Fred object will be used in one or more of
X's methods:
void X::someMethod()
{
x_.goBowling();
}
But now the "disaster scenario" is if someone somewhere somehow calls this
method before the Fred object gets constructed. For example, if
someone else creates a static X object and invokes its
someMethod() method during static initialization, then you're at the
mercy of the compiler as to whether the compiler will construct X::x_
before or after the someMethod() is called. (Note that the ANSI/ISO
C++ committee is working on this problem, but compilers aren't yet generally
available that handle these changes; watch this space for an update in the
future.)
In any event, it's always portable and safe to change the X::x_
static data member into a static member function:
// File X.hpp
class X {
public:
// ...
private:
static Fred& x();
};
Naturally this static member is initialized separately:
// File X.cpp
#include "X.hpp"
Fred& X::x()
{
static Fred* ans = new Fred();
return *ans;
}
Then you simply change any usages of x_ to x():
void X::someMethod()
{
x().goBowling();
}
If you're super performance sensitive and you're concerned about the overhead
of an extra function call on each invocation of X::someMethod() you can
set up a static Fred& instead. As you recall, static local are
only initialized once (the first time control flows over their declaration), so
this will call X::x() only once: the first time X::someMethod()
is called:
void X::someMethod()
{
static Fred& x = X::x();
x.goBowling();
}
Note: You don't have to do this for builtin/intrinsic types like int or
char*. For example if you create a static or global float object, there
is no need to wrap it within a function. The only time the static
initialization order is truly a fiasco is when your static or global
objects have a constructor.
[ Top | Bottom | Previous section | Next section ]
[10.14] How can I handle a constructor that fails?
Throw an exception. See [17.2] for details.
[ Top | Bottom | Previous section | Next section ]
E-mail the author
[ C++ FAQ Lite
| Table of contents
| Subject index
| About the author
| ©
| Download your own copy ]
Revised Jul 10, 2000
|