Search code examples
c++boostshared-ptrsmart-pointers

Do boost::shared_ptr<T> and boost::shared_ptr<const T> share the reference count?


There are several interesting questions on pitfalls with boost::shared_ptrs. In one of them, there is the useful tip to avoid pointing boost::shared_ptr<Base> and boost::shared_ptr<Derived> to the same object of type Derived since they use different reference counts and might destroy the object prematurely.

My question: Is it safe to have both boost::shared_ptr<T> and boost::shared_ptr<const T> point to the same object of type T, or will this cause the same problem?


Solution

  • It is perfectly safe.

    The following code sample:

    #include <iostream>
    #include <boost/shared_ptr.hpp>
    
    int main(int, char**)
    {
      boost::shared_ptr<int> a(new int(5));
      boost::shared_ptr<const int> b = a;
    
      std::cout << "a: " << a.use_count() << std::endl;
      std::cout << "b: " << b.use_count() << std::endl;
    
      return EXIT_SUCCESS;
    }
    

    Compiles and run fine, and is perfectly correct. It outputs:

    a: 2
    b: 2
    

    The two shared_ptr share the same reference counter.


    Also:

    #include <iostream>
    #include <boost/shared_ptr.hpp>
    
    class A {};
    class B : public A {};
    
    int main(int, char**)
    {
        boost::shared_ptr<A> a(new B());
        boost::shared_ptr<B> b = boost::static_pointer_cast<B>(a);
    
        std::cout << "a: " << a.use_count() << std::endl;
        std::cout << "b: " << b.use_count() << std::endl;
    
        return EXIT_SUCCESS;
    }
    

    Behave the same way. You must, however never build your shared_ptr using a construct like this:

    boost::shared_ptr<A> a(new B());
    boost::shared_ptr<B> b(static_cast<B*>(a.get()));
    

    a.get() gives the raw pointer and loses all information about reference counting. Doing this, you'll end up with two distinct (not linked) shared_ptr that use the same pointer but different reference counters.