On Dec 13, 6:47 pm, Leigh Johnston<le...@i42.co.uk> wrote:
On 13/12/2010 18:40, James Kanze wrote:
On Dec 13, 6:17 pm, Leigh Johnston<le...@i42.co.uk> wrote:
On 13/12/2010 11:45, James Kanze wrote:
[...]
As you are doing it wrong it is neither defensive programming
nor sound engineering.
Again, I'd suggest you read my code very, very carefully. (I'll
admit that it's not immediately obvious as to why it works. But
it's been reviewed several times by leading experts, and never
found wanting.)
You are doing it wrong. I say again if you have more than one of your
leaking singletons defined in more than one TU the construction order of
your leaking singletons is unspecified.
This is your code:
namespace {
Singleton* ourInstance =&Singleton::instance();
Singleton&
Singleton::instance()
{
if (ourInstance == NULL)
ourInstance = new Singleton;
return *ourInstance;
}
}
The ourInstance *pointer* is a global object (albeit with internal
linkage) which you are initializing with a dynamic allocation wrapped in
a function.
The ourInstance pointer is *not* a global object. No code
outside the above can access it. (There is a simple error in
the posted code: the function Singleton::instance() shouldn't be
in unnamed namespace, since the class Singleton obviously isn't
in unnamed namespace.)
If you have more than such initialization in more than one
TU the order of the initializations is unspecified.
Yes, but it doesn't matter:
-- ourInstance is initialized to null before any C++ code is
executed (zero initialization).
-- client code cannot access ourInstance; all accesses go
through Singleton::instance().
-- Singleton::instance() checks for null, and initializes the
pointer if necessary, regardless of when it is called. This
is the classic implementation of the singleton pattern, and
ensures that there is no order of initialization problem
when Singleton is used.
-- The "formal" initialization of ourInstance (after the = sign
in its definition ensures that Singleton::instance() is
called at least once during static initialization, and thus
that the pointer is initialized before entering main (in
practice, at least), and thus normally before threading
starts. This is only necessary for thread safety---once the
pointer has been correctly initialized, the code is thread
safe without any synchronization.
Of course it matters. If two of your singletons defined in different
construction* the order of these references is unspecified.