Search code examples
c++shared-ptrraiitr1

Why std::shared_ptr control block need to hold a pointer to managed object with its correct type


I am looking at the shared_ptr implementation in the following post. One question that is not entirely clear to me is, why in addition to the pointer stored with T* type in shared_ptr class itself, author also needs to store the second copy of the managed object's pointer with its concrete type in the control block (i.e. U* p; in auximpl). I understand why we need this for custom deleter, but not for actual pointer. It looks like this complies with the requirements of the standard, when I read control block description in cppreference page. Author made the following comment about this

"this is needed to properly manage all the cases of T being a base for whatever U having multiple T in the derivation hierarchy"

but I still can't come up with an example of when this will really be required. Can someone please demonstrate it with an example?

Thank you, -Grigor


Solution

  • One case is when using shared_ptr's alias capability.

    Create a shared_ptr using an object's member but the control block is the same and thus the reference count.

    class holder : public std::enable_shared_from_this<holder>
    {
     int member;
    
    public:
     
     std::shared_ptr<int> get_member() { 
      return std::shared_ptr<int>(shared_from_this(), &member);
     }
    };
    
    std::shared_ptr<int> foo()
    {
     auto ptr = std::make_shared<holder>();
     return ptr->get_member();
    }
    

    the object created in the make_shared call won't be freed until the object returned from foo's reference count goes to 0.