Search code examples
c++shared-ptrunique-ptr

c++ shared_ptr release ownership


We all know that we can easily convert unique_ptr to shared_ptr in C++. But what if I have made such a conversion :-

unique_ptr<X> u=make_unique<X>();    // X is some class
shared_ptr<X> s=move(u);      // this works of course

And now i want to transfer the ownership of the pointer in s back to u. Sadly there is no release() function in shared_ptr like in unique_ptr else I could have dont something like this :-

u.reset(s.release());

Moreover this also fails to work :-

u.reset(s.get());

Can anyone suggest me how to convert shared_ptr to unique_ptr or atleast release the pointer owned by shared_ptr ?


Solution

  • As everyone has mentioned, you cannot convert shared_ptr to unique_ptr because more than one shared_ptr might be owning the object. Hence there is no release() function for shared_ptr. Had there been one & you would have used release() on one shared_ptr object when more than one of such would be sharing a resource then there would be ambiguity for other shared_ptr pointers as to whether they own the resource or not.

    However, because your actual problem was regarding the static& dynamic casting of unique_ptr (as you have mentioned in your comments) so I would like to add that you needn't actually use shared_ptr for casting unique_ptr & here I show you how you can do so very simply :-

    void dynamic_unique_cast (unique_ptr<Parent> &pa)
    {
        unique_ptr<Child> pb;    
        Parent *p=pa.release();   // release ownership
        try
        {
           pb.reset(dynamic_cast<Child*>(p));  // perform casting
           if (pb==nullptr)
           throw runtime_error {"nullptr exception"};
           cout<<"dynamic_cast successful\n\n";
           pa.reset(pb.release());  // if casting is successful then `pb` returns ownership back to `pa`
        }
        catch (exception &e)
        {
           cout<<"dynamic_cast unsuccessful: "<<e.what()<<"\n\n";
           pa.reset(p);  // if casting fails then `p` returns ownership to `pa`
        }
    }
    void static_unique_cast (unique_ptr<Parent> &pa)
    {
        unique_ptr<Child> pb;
        Parent *p=pa.release();
        try
        {
           pb.reset(static_cast<Child*>(p));
           if (pb==nullptr)
           throw runtime_error {"nullptr exception"};
           show(pb);
           cout<<"static_cast successful\n\n";
           pa.reset(pb.release());
        }
        catch (exception &e)
        {
           cout<<"static_cast unsuccessful: "<<e.what()<<"\n\n";
           pa.reset(p);
        }
    }
    

    The above code works pretty well & will definitely solve your problem. If you have any ambiguity then feel free to comment.