Virus721 Virus721 - 2 months ago 12
C++ Question

weak_ptr - Dereferencing - Throw if expired

Dereferencing a

weak_ptr
does not automatically check whether the pointer has expired. Why is it designed this way ?

I would like to safely dereference weak pointers without first having to check them using
expired()
and throw an exception if they are null.

Would this be a good practice and what would be a right way to do that ? Should I overload
*
and
->
operators so that they perform this check first ? Should I write a free function ?

Something like :

template< typename T >
weak_ptr< T > & check( weak_ptr< T > & p )
{
if( p.expired() )
throw logic_error( "Trying to dereference a null pointer." );
return p;
}


And then :

weak_ptr< int > pi;
int i = *check( pi );


Thank you.

Answer

Using expired() is not useful because it will introduce races in multi-threaded programs. Also an exception is not nice, because having a weak_ptr expired is not so exceptional: they are designed precisely for that.

The nice trick around weak_ptr is that they are not dereferenceable. Instead, to access the object you call lock() that atomically returns a shared_ptr that points to the object, or to null if not available.

The normal way to access a weak pointer is:

void safe_do(weak_ptr<T> &w)
{
    shared_ptr<T> p = w.lock();
    if (p)
        p->do();
}

If you really want the exception, you can use this variant:

void safe_do2(weak_ptr<T> &w)
{
    shared_ptr<T> p(w); //throws if w expired
    p->do();
}
Comments