Search code examples
c++pointersexceptionweak-ptr

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.


Solution

  • 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>(w)->do(); //throws a bad_weak_ptr if w expired
    }