[10] Constructors
(Part of C++ FAQ Lite, Copyright © 1991-2006, 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 sectionSearch the FAQ ]


[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 sectionSearch the FAQ ]


[10.3] Can one constructor of a class call another constructor of the same class to initialize the this object?

Nope.

Let's work an example. Suppose you want your constructor Foo::Foo(char) to call another constructor of the same class, say Foo::Foo(char,int), in order that Foo::Foo(char,int) would help initialize the this object. Unfortunately there's no way to do this in C++.

Some people do it anyway. Unfortunately it doesn't do what they want. For example, the line Foo(x, 0); does not call Foo::Foo(char,int) on the this object. Instead it calls Foo::Foo(char,int) to initialize a temporary, local object (not this), then it immediately destructs that temporary when control flows over the ;.

 class Foo {
 public:
   Foo(char x);
   Foo(char x, int y);
   
...
 };
 
 Foo::Foo(char x)
 {
   
...
   Foo(x, 0);  
// this line does NOT help initialize the this object!!
   
...
 }

You can sometimes combine two constructors via a default parameter:

 class Foo {
 public:
   Foo(char x, int y=0);  
// this line combines the two constructors
   
...
 };

If that doesn't work, e.g., if there isn't an appropriate default parameter that combines the two constructors, sometimes you can share their common code in a private init() member function:

 class Foo {
 public:
   Foo(char x);
   Foo(char x, int y);
   
...
 private:
   void init(char x, int y);
 };
 
 Foo::Foo(char x)
 {
   init(x, int(x) + 7);
   
...
 }
 
 Foo::Foo(char x, int y)
 {
   init(x, y);
   
...
 }
 
 void Foo::init(char x, int y)
 {
   
...
 }

BTW do NOT try to achieve this via placement new. Some people think they can say new(this) Foo(x, int(x)+7) within the body of Foo::Foo(char). However that is bad, bad, bad. Please don't write me and tell me that it seems to work on your particular version of your particular compiler; it's bad. Constructors do a bunch of little magical things behind the scenes, but that bad technique steps on those partially constructed bits. Just say no.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[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. One example of this is a constructor that takes no parameters:

 class Fred {
 public:
   Fred();   
// Default constructor: can be called with no args
   
...
 };

Another example of a "default constructor" is one that 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 sectionSearch the FAQ ]


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

Fred's default constructor (except as discussed below).

 class Fred {
 public:
   Fred();
   
...
 };
 
 int main()
 {
   Fred a[10];              
 calls the default constructor 10 times
   Fred* p = new Fred[10];  
 calls the default constructor 10 times
   
...
 }

If your class doesn't have a default constructor, you'll get a compile-time error when you attempt to create an array using the above simple syntax:

 class Fred {
 public:
   Fred(int i, int j);      
 assume there is no default constructor
   
...
 };
 
 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, even if your class already has a default constructor, you should try to use std::vector<Fred> rather than an array (arrays are evil). std::vector lets you decide to use any constructor, not just the default constructor:

 #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, you might need the "explicit initialization of arrays" syntax. Here's how:

 class Fred {
 public:
   Fred(int i, int j);      
 assume there is no default constructor
   
...
 };
 
 int main()
 {
   Fred a[10] = {
     Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7),  
// The 10 Fred objects are
     Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7)   
// initialized using 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.

Finally, you can use placement-new to manually initialize the elements of the array. Warning: it's ugly: the raw array can't be of type Fred, so you'll need a bunch of pointer-casts to do things like compute array index operations. Warning: it's compiler- and hardware-dependent: you'll need to make sure the storage is aligned with an alignment that is at least as strict as is required for objects of class Fred. Warning: it's tedious to make it exception-safe: you'll need to manually destruct the elements, including in the case when an exception is thrown part-way through the loop that calls the constructors. But if you really want to do it anyway, read up on placement-new. (BTW placement-new is the magic that is used inside of std::vector. The complexity of getting everything right is yet another reason to use std::vector.)

By the way, did I ever mention that arrays are evil? Or did I mention that you ought to use a std::vector unless there is a compelling reason to use an array?

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[10.6] Should my constructors use "initialization lists" or "assignment"?

Initialization lists. In fact, constructors should initialize as a rule all member objects in the initialization list. One exception is discussed further down.

Consider the following constructor that initializes member object x_ using an initialization list: Fred::Fred() : x_(whatever) { }. The most common benefit of doing this is improved performance. For example, if the expression whatever is the same type as member variable x_, the result of the whatever expression is constructed directly inside x_ — the compiler does not make a separate copy of the object. Even if the types are not the same, the compiler is usually able to do a better job with initialization lists than with assignments.

The other (inefficient) way to build constructors is via assignment, such as: 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 that temporary object is destructed at the ;. That's inefficient.

As if that wasn't bad enough, there's another source of inefficiency when using assignment in a constructor: the member object will get fully constructed by its default constructor, and this 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.

Note: There is no performance difference if the type of x_ is some built-in/intrinsic type, such as int or char* or float. But even in these cases, my personal preference is to set those data members in the initialization list rather than via assignment for consistency. Another symmetry argument in favor of using initialization lists even for built-in/intrinsic types: non-static const and non-static reference data members can't be assigned a value in the constructor, so for symmetry it makes sense to initialize everything in the initialization list.

Now for the exceptions. Every rule has exceptions (hmmm; does "every rule has exceptions" have exceptions? reminds me of Gödel's Incompleteness Theorems), and there are a couple of exceptions to the "use initialization lists" rule. Bottom line is to use common sense: if it's cheaper, better, faster, etc. to not use them, then by all means, don't use them. This might happen when your class has two constructors that need to initialize the this object's data members in different orders. Or it might happen when two data members are self-referential. Or when a data-member needs a reference to the this object, and you want to avoid a compiler warning about using the this keyword prior to the { that begins the constructor's body (when your particular compiler happens to issue that particular warning). Or when you need to do an if/throw test on a variable (parameter, global, etc.) prior to using that variable to initialize one of your this members. This list is not exhaustive; please don't write me asking me to add another "Or when...". The point is simply this: use common sense.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


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

Here is something that always works: the {body} of a constructor (or a function called from the constructor) can reliably access the data members declared in a base class and/or the data members declared in the constructor's own class. This is because all those data members are guaranteed to have been fully constructed by the time the constructor's {body} starts executing.

Here is something that never works: the {body} of a constructor (or a function called from the constructor) cannot get down to a derived class by calling a virtual member function that is overridden in the derived class. If your goal was to get to the overridden function in the derived class, you won't get what you want. Note that you won't get to the override in the derived class independent of how you call the virtual member function: explicitly using the this pointer (e.g., this->method()), implicitly using the this pointer (e.g., method()), or even calling some other function that calls the virtual member function on your this object. The bottom line is this: even if the caller is constructing an object of a derived class, during the constructor of the base class, your object is not yet of that derived class. You have been warned.

Here is something that sometimes works: if you pass any of the data members in this object to another data member's initializer, you must make sure that the other data member has already been initialized. The good news is that you can determine whether the other data member has (or has not) been initialized using some straightforward language rules that are independent of the particular compiler you're using. The bad news it that you have to know those language rules (e.g., base class sub-objects are initialized first (look up the order if you have multiple and/or virtual inheritance!), then data members defined in the class are initialized in the order in which they appear in the class declaration). If you don't know these rules, then don't pass any data member from the this object (regardless of whether or not you explicitly use the this keyword) to any other data member's initializer! And if you do know the rules, please be careful.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


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

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 them become 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.

Note that the Named Constructor Idiom, at least as implemented above, is just as fast as directly calling a constructor — modern compilers will not make any extra copies of your object.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[10.9] Does return-by-value mean extra copies and extra overhead?

Not necessarily.

All(?) commercial-grade compilers optimize away the extra copy, at least in cases as illustrated in the previous FAQ.

To keep the example clean, let's strip things down to the bare essentials. Suppose yourCode() calls rbv() ("rbv" stands for "return by value") which returns a Foo object by value:

 class Foo { ... };
 
 Foo rbv();
 
 void yourCode()
 {
   Foo x = rbv(); 
 the return-value of rbv() goes into x
   
...
 }

Now the question is, How many Foo objects will there be? Will rbv() create a temporary Foo object that gets copy-constructed into x? How many temporaries? Said another way, does return-by-value necessarily degrade performance?

The point of this FAQ is that the answer is No, commercial-grade C++ compilers implement return-by-value in a way that lets them eliminate the overhead, at least in simple cases like those shown in the previous FAQ. In particular, all(?) commercial-grade C++ compilers will optimize this case:

 Foo rbv()
 {
   
...
   return Foo(42, 73); 
 suppose Foo has a ctor Foo::Foo(int a, int b)
 }

Certainly the compiler is allowed to create a temporary, local Foo object, then copy-construct that temporary into variable x within yourCode(), then destruct the temporary. But all(?) commercial-grade C++ compilers won't do that: the return statement will directly construct x itself. Not a copy of x, not a pointer to x, not a reference to x, but x itself.

You can stop here if you don't want to genuinely understand the previous paragraph, but if you want to know the secret sauce (so you can, for example, reliably predict when the compiler can and cannot provide that optimization for you), the key is to know that compilers usually implement return-by-value using pass-by-pointer. When yourCode() calls rbv(), the compiler secretly passes a pointer to the location where rbv() is supposed to construct the "returned" object. It might look something like this (it's shown as a void* rather than a Foo* since the Foo object has not yet been constructed):

 // Pseudo-code
 void rbv(void* put_result_here) 
 Original C++ code: Foo rbv()
 {
   
...
 }
 
 
// Pseudo-code
 void yourCode()
 {
   struct Foo x;
   rbv(&x); 
 Original C++ code: Foo x = rbv()
   
...
 }

So the first ingredient in the secret sauce is that the compiler (usually) transforms return-by-value into pass-by-pointer. This means that commercial-grade compilers don't bother creating a temporary: they directly construct the returned object in the location pointed to by put_result_here.

The second ingredient in the secret sauce is that compilers typically implement constructors using a similar technique. This is compiler-dependent and somewhat idealized (I'm intentionally ignoring how to handle new and overloading), but compilers typically implement Foo::Foo(int a, int b) using something like this:

 // Pseudo-code
 void Foo_ctor(Foo* this, int a, int b) 
 Original C++ code: Foo::Foo(int a, int b)
 {
   
...
 }

Putting these together, the compiler might implement the return statement in rbv() by simply passing put_result_here as the constructor's this pointer:

 // Pseudo-code
 void rbv(void* put_result_here) 
 Original C++ code: Foo rbv()
 {
   
...
   Foo_ctor((Foo*)put_result_here, 42, 73); 
 Original C++ code: return Foo(42,73);
   return;
 }

So yourCode() passes &x to rbv(), and rbv() in turn passes &x to the constructor (as the this pointer). That means constructor directly constructs x.

In the early 90s I did a seminar for IBM's compiler group in Toronto, and one of their engineers told me that they found this return-by-value optimization to be so fast that you get it even if you don't compile with optimization turned on. Because the return-by-value optimization causes the compiler to generate less code, it actually improves compile-times in addition to making your generated code smaller and faster. The point is that the return-by-value optimization is almost universally implemented, at least in code cases like those shown above.

Some compilers also provide the return-by-value optimization your function returns a local variable by value, provided all the function's return statements return the same local variable. This requires a little more work on the part of the compiler writers, so it isn't universally implemented; for example, GNU g++ 3.3.3 does it but Microsoft Visual C++.NET 2003 does not:

 // Actual C++ code for rbv()
 Foo rbv()
 {
   
...
   Foo ans = Foo(42, 73);
   
...
   do_something_with(ans);
   
...
   return ans;
 }

The compiler might construct ans in a local object, then in the return statement copy-construct ans into the location pointed to by put_result_here and destruct ans. But if all return statements return the same local object, in this case ans, the compiler is also allowed to construct ans in the location pointed to by put_result_here:

 // Pseudo-code
 void rbv(void* put_result_here) 
 Original C++ code: Foo rbv()
 {
   
...
   Foo_ctor((Foo*)put_result_here, 42, 73); 
 Original C++ code: Foo ans = Foo(42,73);
   
...
   do_something_with(*(Foo*)put_result_here); 
 Original C++ code: do_something_with(ans);
   
...
   return; 
 Original C++ code: return ans;
 }

Final thought: this discussion was limited to whether there will be any extra copies of the returned object in a return-by-value call. Don't confuse that with other things that could happen in yourCode(). For example, if you changed yourCode() from Foo x = rbv(); to Foo x; x = rbv(); (note the ; after the declaration), the compiler is required to use Foo's assignment operator, and unless the compiler can prove that Foo's default constructor followed by assignment operator is exactly the same as its copy constructor, the compiler is required by the language to put the returned object into an unnamed temporary within yourCode(), use the assignment operator to copy the temporary into x, then destruct the temporary. The return-by-value optimization still plays its part since there will be only one temporary, but by changing Foo x = rbv(); to Foo x; x = rbv();, you have prevented the compiler from eliminating that last temporary.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[10.10] 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 sectionSearch the FAQ ]


[10.11] 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 sectionSearch the FAQ ]


[10.12] What's the "static initialization order fiasco"?

A subtle way to crash your program.

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 initialization for the y object (typically the y object's constructor) 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 initialization will get run before x's initialization, and you're toast. E.g., y's constructor could 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 can also, in some cases, apply to built-in/intrinsic types.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[10.13] 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.h"
 Fred x;

The file y.cpp defines the y object:

 // File y.cpp
 #include "Barney.h"
 Barney y;

For completeness the Barney constructor might look something like this:

 // File Barney.cpp
 #include "Barney.h"
 
 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.h"
 
 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.h"
 
 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. There is another technique that answers this concern, but it needs to be used with care since it creates the possibility of another (equally nasty) problem.

Note: The static initialization order fiasco can also, in some cases, apply to built-in/intrinsic types.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[10.14] Why doesn't the construct-on-first-use idiom use a static object instead of a static pointer?

Short answer: it's possible to use a static object rather than a static pointer, but doing so opens up another (equally subtle, equally nasty) problem.

Long answer: sometimes people worry about the fact that the previous solution "leaks." In many cases, this is not a problem, but it is a problem in some cases. Note: even though the object pointed to by ans in the previous FAQ is never deleted, the memory doesn't actually "leak" when the program exits since the operating system automatically reclaims all the memory in a program's heap when that program exits. In other words, the only time you'd need to worry about this is when the destructor for the Fred object performs some important action (such as writing something to a file) that must occur sometime while the program is exiting.

In those cases where the construct-on-first-use object (the Fred, in this case) needs to eventually get destructed, you might consider changing function x() as follows:

 // File x.cpp
 
 #include "Fred.h"
 
 Fred& x()
 {
   static Fred ans;  
// was static Fred* ans = new Fred();
   return ans;       
// was return *ans;
 }

However there is (or rather, may be) a rather subtle problem with this change. To understand this potential problem, let's remember why we're doing all this in the first place: we need to make 100% sure our static object (a) gets constructed prior to its first use and (b) doesn't get destructed until after its last use. Obviously it would be a disaster if any static object got used either before construction or after destruction. The message here is that you need to worry about two situations (static initialization and static deinitialization), not just one.

By changing the declaration from static Fred* ans = new Fred(); to static Fred ans;, we still correctly handle the initialization situation but we no longer handle the deinitialization situation. For example, if there are 3 static objects, say a, b and c, that use ans during their destructors, the only way to avoid a static deinitialization disaster is if ans is destructed after all three.

The point is simple: if there are any other static objects whose destructors might use ans after ans is destructed, bang, you're dead. If the constructors of a, b and c use ans, you should normally be okay since the runtime system will, during static deinitialization, destruct ans after the last of those three objects is destructed. However if a and/or b and/or c fail to use ans in their constructors and/or if any code anywhere gets the address of ans and hands it to some other static object, all bets are off and you have to be very, very careful.

There is a third approach that handles both the static initialization and static deinitialization situations, but it has other non-trivial costs. I'm too lazy (and busy!) to write any more FAQs today so if you're interested in that third approach, you'll have to buy a book that describes that third approach in detail. The C++ FAQs book is one of those books, and it also gives the cost/benefit analysis to decide if/when that third approach should be used.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[10.15] 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.h
 
 class X {
 public:
   
...
 
 private:
   static Fred x_;
 };

Naturally this static member is initialized separately:

 // File X.cpp
 
 #include "X.h"
 
 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.h
 
 class X {
 public:
   
...
 
 private:
   static Fred& x();
 };

Naturally this static member is initialized separately:

 // File X.cpp
 
 #include "X.h"
 
 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: The static initialization order fiasco can also, in some cases, apply to built-in/intrinsic types.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[10.16] Do I need to worry about the "static initialization order fiasco" for variables of built-in/intrinsic types?

Yes.

If you initialize your built-in/intrinsic type using a function call, the static initialization order fiasco is able to kill you just as bad as with user-defined/class types. For example, the following code shows the failure:

 #include <iostream>
 
 int f();  
// forward declaration
 int g();  
// forward declaration
 
 int x = f();
 int y = g();
 
 int f()
 {
   std::cout << "using 'y' (which is " << y << ")\n";
   return 3*y + 7;
 }
 
 int g()
 {
   std::cout << "initializing 'y'\n";
   return 5;
 }

The output of this little program will show that it uses y before initializing it. The solution, as before, is the Construct On First Use Idiom:

 #include <iostream>
 
 int f();  
// forward declaration
 int g();  
// forward declaration
 
 int& x()
 {
   static int ans = f();
   return ans;
 }
 
 int& y()
 {
   static int ans = g();
   return ans;
 }
 
 int f()
 {
   std::cout << "using 'y' (which is " << y() << ")\n";
   return 3*y() + 7;
 }
 
 int g()
 {
   std::cout << "initializing 'y'\n";
   return 5;
 }

Of course you might be able to simplify this by moving the initialization code for x and y into their respective functions:

 #include <iostream>
 
 int& y();  
// forward declaration
 
 int& x()
 {
   static int ans;
 
   static bool firstTime = true;
   if (firstTime) {
     firstTime = false;
     std::cout << "using 'y' (which is " << y() << ")\n";
     ans = 3*y() + 7;
   }
 
   return ans;
 }
 
 int& y()
 {
   static int ans;
 
   static bool firstTime = true;
   if (firstTime) {
     firstTime = false;
     std::cout << "initializing 'y'\n";
     ans = 5;
   }
 
   return ans;
 }

And, if you can get rid of the print statements you can further simplify these to something really simple:

 int& y();  // forward declaration
 
 int& x()
 {
   static int ans = 3*y() + 7;
   return ans;
 }
 
 int& y()
 {
   static int ans = 5;
   return ans;
 }

Furthermore, since y is initialized using a constant expression, it no longer needs its wrapper function — it can be a simple variable again.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


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

Throw an exception. See [17.2] for details.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[10.18] What is the "Named Parameter Idiom"?

It's a fairly useful way to exploit method chaining.

The fundamental problem solved by the Named Parameter Idiom is that C++ only supports positional parameters. For example, a caller of a function isn't allowed to say, "Here's the value for formal parameter xyz, and this other thing is the value for formal parameter pqr." All you can do in C++ (and C and Java) is say, "Here's the first parameter, here's the second parameter, etc." The alternative, called named parameters and implemented in the language Ada, is especially useful if a function takes a large number of mostly default-able parameters.

Over the years people have cooked up lots of workarounds for the lack of named parameters in C and C++. One of these involves burying the parameter values in a string parameter then parsing this string at run-time. This is what's done in the second parameter of fopen(), for example. Another workaround is to combine all the boolean parameters in a bit-map, then the caller or's a bunch of bit-shifted constants together to produce the actual parameter. This is what's done in the second parameter of open(), for example. These approaches work, but the following technique produces caller-code that's more obvious, easier to write, easier to read, and is generally more elegant.

The idea, called the Named Parameter Idiom, is to change the function's parameters to methods of a newly created class, where all these methods return *this by reference. Then you simply rename the main function into a parameterless "do-it" method on that class.

We'll work an example to make the previous paragraph easier to understand.

The example will be for the "open a file" concept. Let's say that concept logically requires a parameter for the file's name, and optionally allows parameters for whether the file should be opened read-only vs. read-write vs. write-only, whether or not the file should be created if it doesn't already exist, whether the writing location should be at the end ("append") or the beginning ("overwrite"), the block-size if the file is to be created, whether the I/O is buffered or non-buffered, the buffer-size, whether it is to be shared vs. exclusive access, and probably a few others. If we implemented this concept using a normal function with positional parameters, the caller code would be very difficult to read: there'd be as many as 8 positional parameters, and the caller would probably make a lot of mistakes. So instead we use the Named Parameter Idiom.

Before we go through the implementation, here's what the caller code might look like, assuming you are willing to accept all the function's default parameters:

 File f = OpenFile("foo.txt");

That's the easy case. Now here's what it might look like if you want to change a bunch of the parameters.

 File f = OpenFile("foo.txt")
            .readonly()
            .createIfNotExist()
            .appendWhenWriting()
            .blockSize(1024)
            .unbuffered()
            .exclusiveAccess();

Notice how the "parameters", if it's fair to call them that, are in random order (they're not positional) and they all have names. So the programmer doesn't have to remember the order of the parameters, and the names are (hopefully) obvious.

So here's how to implement it: first we create a class (OpenFile) that houses all the parameter values as private data members. The required parameters (in this case, the only required parameter is the file's name) is implemented as a normal, positional parameter on OpenFile's constructor, but that constructor doesn't actually open the file. Then all the optional parameters (readonly vs. readwrite, etc.) become methods. These methods (e.g., readonly(), blockSize(unsigned), etc.) return a reference to their this object so the method calls can be chained.

 class File;
 
 class OpenFile {
 public:
   OpenFile(const std::string& filename);
     
// sets all the default values for each data member
   OpenFile& readonly();  
// changes readonly_ to true
   OpenFile& readwrite(); 
// changes readonly_ to false
   OpenFile& createIfNotExist();
   OpenFile& blockSize(unsigned nbytes);
   
...
 private:
   friend class File;
   std::string filename_;
   bool readonly_;          
// defaults to false [for example]
   bool createIfNotExist_;  
// defaults to false [for example]
   
...
   unsigned blockSize_;     
// defaults to 4096 [for example]
   
...
 };
 
 inline OpenFile::OpenFile(const std::string& filename)
   : filename_         (filename)
   , readonly_         (false)
   , createIfNotExist_ (false)
   , blockSize_        (4096u)
 { }
 
 inline OpenFile& OpenFile::readonly()
 { readonly_ = true; return *this; }
 
 inline OpenFile& OpenFile::readwrite()
 { readonly_ = false; return *this; }
 
 inline OpenFile& OpenFile::createIfNotExist()
 { createIfNotExist_ = true; return *this; }
 
 inline OpenFile& OpenFile::blockSize(unsigned nbytes)
 { blockSize_ = nbytes; return *this; }

The only other thing to do is make the constructor for class File to take an OpenFile object:

 class File {
 public:
   File(const OpenFile& params);
   
...
 };

This constructor gets the actual parameters from the OpenFile object, then actually opens the file:

 File::File(const OpenFile& params)
 {
   
...
 }

Note that OpenFile declares File as its friend, that way OpenFile doesn't need a bunch of (otherwise useless) public: get methods.

Since each member function in the chain returns a reference, there is no copying of objects and the chain is highly efficient. Furthermore, if the various member functions are inline, the generated object code will probably be on par with C-style code that sets various members of a struct. Of course if the member functions are not inline, there may be a slight increase in code size and a slight decrease in performance (but only if the construction occurs on the critical path of a CPU-bound program; this is a can of worms I'll try to avoid opening; read the C++ FAQs book for a rather thorough discussion of the issues), so it may, in this case, be a tradeoff for making the code more reliable.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


[10.19] Why am I getting an error after declaring a Foo object via Foo x(Bar())?

Because that doesn't create a Foo object - it declares a non-member function that returns a Foo object.

This is really going to hurt; you might want to sit down.

First, here's a better explanation of the problem. Suppose there is a class called Bar that has a default ctor. This might even be a library class such as std::string, but for now we'll just call it Bar:

 class Bar {
 public:
   Bar();
   
...
 };

Now suppose there's another class called Foo that has a ctor that takes a Bar. As before, this might be defined by someone other than you.

 class Foo {
 public:
   Foo(const Bar& b);  
// or perhaps Foo(Bar b)
   
...
   void blah();
   
...
 };

Now you want to create a Foo object using a temporary Bar. In other words, you want to create an object via Bar(), and pass that to the Foo ctor to create a local Foo object called x:

 void yourCode()
 {
   Foo x(Bar());  
 you think this creates a Foo object called x...
   x.blah();      
 ...but it doesn't, so this line gives you a bizarre error message
   
...
 }

It's a long story, but the solution (hope you're sitting down!) is to use = in your declaration:

 void yourCode()
 {
   Foo x = Foo(Bar());  
 Yes, Virginia, that thar syntax really works
   x.blah();            
 Ahhhh, this works now — no more error messages
   
...
 }

Here's why that happens (this part is optional; only read it if you think your future as a programmer is worth two minutes of your precious time today): When the compiler sees Foo x(Bar()), it thinks that the Bar() part is declaring a non-member function that returns a Bar object, so it thinks you are declaring the existence of a function called x that returns a Foo and that takes as a single parameter of type "non-member function that takes nothing and returns a Bar."

Now here's the sad part. In fact it's pathetic. Some mindless drone out there is going to skip that last paragraph, then they're going to impose a bizarre, incorrect, irrelevant, and just plain stupid coding standard that says something like, "Never create temporaries using a default constructor" or "Always use = in all initializations" or something else equally inane. If that's you, please fire yourself before you do any more damage. Those who don't understand the problem shouldn't tell others how to solve it. Harumph.

(Okay, that was mostly tongue in cheek. But there's a grain of truth in it. The real problem is that people tend to worship consistency, and they tend to extrapolate from the obscure to the common. That's not wise.)

Follow-up: if your Foo::Foo(const Bar&) constructor is not explicit, and if Foo's copy constructor is accessible, you can use this syntax instead: Foo x = Bar();.

TopBottomPrevious sectionNext sectionSearch the FAQ ]


E-Mail E-mail the author
C++ FAQ LiteTable of contentsSubject indexAbout the author©Download your own copy ]
Revised Mar 1, 2006