|
||||
|
Section 10:
|
[10.17] 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.
|
|||