Search code examples
c++shared-ptr

Does static_pointer_cast update reference counting


I have recently found out about replacing:

std::shared_ptr<NEWT>(static_cast<NEWT>(old_ptr.get()));

with

std::static_pointer_cast<NEWT>(odl_ptr);

I know that the former solution may result in double delete if one is not careful.

I was wondering if the reference counting is updated with the latter solution, and how is that achievable?


Solution

  • Using static_pointer_cast or dynamic_pointer_cast enables the generated shared_ptr to do proper reference counting without resulting in double deletes. This is achieved by calling a special constructor for the resulting casted pointer, here is an example implementation:

    template< class T, class U > 
    std::shared_ptr<T> static_pointer_cast( const std::shared_ptr<U>& r ) noexcept
    {
        auto p = static_cast<typename std::shared_ptr<T>::element_type*>(r.get());
        return std::shared_ptr<T>(r, p);
    }
    

    Notice that the constructor called is

    std::shared_ptr<T>(r,p);
    

    which actually is of the form

    template< class Y >
    shared_ptr( const shared_ptr<Y>& r, T *ptr );
    

    The latter is an aliasing constructor, meaning that the object is managed by r, and the constructed shared_ptr is unamanaged. To have the same behaviour without the static_cast_pointer one would have to write

    std::shared_ptr<T>(r, static_cast<T>(odl_ptr.get());
    

    where your old_ptr is of some other type.

    some code from here