Is it possible to initialize the Instance of a Singleton when it is really needed?
Consider this pattern taken from the famous "Design Patterns":
class Singleton {
public:
static Singleton* Instance();
protected:
Singleton();
private:
static Singleton* _instance;
}
Singleton* Singleton::_instance = 0; // unit.cpp
static Singleton* Singleton::Instance() {
if (_instance == 0) {
_instance = new Singleton;
}
return _instance;
}
Now, I think there is a problem in the pattern there, if one desires to provide the Singleton in a library to others: if the user calls Singleton::Instance()
from another compilation unit (during a static data member initialization, for example) before _instance is initialized, then a following call of Singleton::Instance()
might create another instance of the Singleton, with unwanted results, since _instance might have been initialized to 0 first.
I think one solution is to initialize _instance this way:
Singleton* Singleton::_instance = Singleton::Instance();
Anyway, that makes the initialization not "lazy" for those who don't need to call Singleton::Instance() to initialize their static data.
Are there better solutions so that the inizialization can happen when the Singleton instance is needed?
use local statics
Static initialization happens before dynamic initialization
The singleton solution you have quoted works because
describes a static initialization (namely zero initialization in this case, but a constant initialization would work as well if used), which is guaranteed to happen before any dynamic initialization (and therefore before any code is run). All requirements of static initialization are guaranteed here, as _instance is a global variable of a built-in type (a pointer) and initialized with zero.
The other solution you have provided does not change anything significant, because still only the zero initialization of _instance is guaranteed to happen before code from other modules is called, as the initialization by Singleton::Instance call is a dynamic one and therefore is subject to static initialization order fiasco.
Implementation - data segment
Note: Static initialization is most often implemented by storing the value of the variable, which was computed compile time, in a data segment of the executable.
Terminology, standard quote
While most programmers (including Bjarne Stroustrup) call the initialization style used in the original singleton implemementation "compile time initialization", the standard calls it "static initialization", as opposed to a "dynamic initialization" (which is what is most often called run-time). See C++0x draft 3.6.2 (shortened, emphasis mine):
No problem: static variables are zero-initialized before any dynamic initialization takes place.
On the other hand, the code you then introduce as solution to non-existent problem, namely
is problematic – no guarantee about order of (dynamic) initialization between translation unit.
Cheers & hth.,