Reputation: 8335
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.
Upvotes: 4
Views: 4745
Reputation: 98486
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
}
Upvotes: 12