[10] Constructors
(Part of C++ FAQ Lite, Copyright © 1991-2000, Marshall Cline, cline@parashift.com)


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.

TopBottomPrevious sectionNext 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)
   
// ...
 }

TopBottomPrevious sectionNext 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.

TopBottomPrevious sectionNext 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
   
// ...
 };

TopBottomPrevious sectionNext section ]


[10.5] Which constructor gets called when I create an array of Fred objects? UPDATED!

[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.

TopBottomPrevious sectionNext 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.

TopBottomPrevious sectionNext 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.

TopBottomPrevious sectionNext section ]


[10.8] What is the "Named Constructor Idiom"? UPDATED!

[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.

TopBottomPrevious sectionNext 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;

TopBottomPrevious sectionNext 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).

TopBottomPrevious sectionNext 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.

TopBottomPrevious sectionNext 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.

TopBottomPrevious sectionNext 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.

TopBottomPrevious sectionNext section ]


[10.14] How can I handle a constructor that fails?

Throw an exception. See [17.2] for details.

TopBottomPrevious sectionNext section ]


E-Mail E-mail the author
C++ FAQ LiteTable of contentsSubject indexAbout the author©Download your own copy ]
Revised Jul 10, 2000