Is this a valid singleton class?
Now, after the edit the answer is yes, it is valid & it is also thread safe since all non-function-scope static variables are constructed before main()
, while there is only one active thread.
C++ Standard n3337 § 3.6.2/1 § 3.6.2/2: Initialization of non-local variables
There are two broad classes of named non-local variables: those with static storage duration (3.7.1) and those with thread storage duration (3.7.2). Non-local variables with static storage duration are initialized as a consequence of program initiation. Non-local variables with thread storage duration are initialized as a consequence of thread execution. Within each of these phases of initiation, initialization occurs as follows.
Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place. Constant initialization is performed:
— if each full-expression (including implicit conversions) that appears in the initializer of a reference with static or thread storage duration is a constant expression (5.19) and the reference is bound to an lvalue designating an object with static storage duration or to a temporary (see 12.2);
— if an object with static or thread storage duration is initialized by a constructor call, if the constructor is a constexpr constructor, if all constructor arguments are constant expressions (including conversions), and if, after function invocation substitution (7.1.5), every constructor call and full-expression in the mem-initializers and in the brace-or-equal-initializers for non-static data members is a constant expression;
— if an object with static or thread storage duration is not initialized by a constructor call and if every full-expression that appears in its initializer is a constant expression.
Together, zero-initialization and constant initialization are called static initialization; all other initial- ization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place. (...)
C++ Standard n3337 § 6.7/4: Declaration statement
The zero-initialization (8.5) of all block-scope variables with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed before any other initialization takes place. Constant initialization (3.6.2) of a block-scope entity with static storage duration, if applicable, is performed before its block is first entered. An implementation is permitted to perform early initialization of other block-scope variables with static or thread storage duration under the same conditions that an implementation is permitted to statically initialize a variable with static or thread storage duration in namespace scope. Otherwise such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization*). (...)
*):
The implementation must not introduce any deadlock around execution of the initializer.
But it is still prone to static initialization order fiasco. The common way to write getInstance
is:
Singleton& getInstance()
{
static Singleton instance;
return instance;
}
This way you can avoid this initialization problem.
Is this a thread-safe singleton class?
In C++11 above code is thread safe. In C++03 you can use
Besides this you should also prevent from copying and assignment:
Singleton( Singleton const&); // Don't Implement
void operator=( Singleton const&); // Don't implement