From: Jason Hise (chaos_at_[hidden])
Date: 2005-04-28 14:50:35
Rob Stewart wrote:
>From: Jason Hise <chaos_at_[hidden]>
>>Rob Stewart wrote:
>>>As I understand it, the operation is inherently unsafe; it isn't
>>>a matter of efficiency, or even desirable usage. Given that, it
>>>is most appropriate that you spell things differently. You want
>>>to call attention to such usage.
>>Even though the usage is undesirable, it may still be necessary in cases
>>where the singleton needs to behave polymorphically like one of its base
>But you said that the object may not exist since it is
>operator ->() that does the lifetime management. Thus, the
>object may not actually exist when you call the unsafe function,
>so it is a dangerous operation. Did I misunderstand something?
operator-> is not solely responsible for lifetime management. Depending
on the specific traits specified, automatic creation of the singleton
instance can happen at various times. During a call to operator -> is
just one of these times.
There are explicit create and destroy member functions, and the
singleton is generally scheduled to be automatically destroyed at one
point or another. As a result, the automatic creation when operator ->
is invoked is generally a last line of defense, which will recreate the
instance if it has been destroyed (or in some rare circumstances will
create the instance for the first time).
So long as client code makes sure that the instance has already been
created, that nothing destroys the instance while the raw pointer is in
use, and that operations which need to be locked are locked manually,
then that raw pointer is safe to use.
>>>Having said that, is it really the case that operator *()
>>>couldn't do the same work as operator ->() (possibly adding an
>>>exception if you can't get the underlying object)?
>>The difference is that the pointer returned by operator -> is guaranteed
>>to be used immediately, and by using an intermediate pointer class I can
>>construct a lock for the duration of the member call (this technique is
>>described in Modern C++ Design, in the smart pointer section).
>So you're returning a proxy from operator ->(), right?
>>Operator * is incapable of constructing this type of temporary lock, and
>>additionally there is no guarantee that the reference returned would
>>used and discarded immediately. Once the actual reference is returned,
>>no more checking can take place.
>Why can't you return such a proxy from a member function like
>"get" or "get_object" and let that proxy convert to the singleton
>That means you can spell "get_unsafe_ptr" without "unsafe"
>because the proxy ensures that it is safe (as safe as with
>operator ->(), anyway).
The action of getting the pointer itself is not unsafe. What is unsafe
is maintaining that pointer and storing it for an extended period of
time, during which the singleton could be destroyed and recreated.
In almost every circumstance, it is preferable for client code to use
and pass around singleton::pointers rather than singleton *s, just like
it is preferable for client code to use smart pointers to manage memory
rather than trying to manage memory and raw pointers manually. Managing
them manually can be done safely, but it is harder and error prone.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk