Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ shared_ptr release ownership [duplicate]

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 ?

like image 344
Anwesha Avatar asked Oct 10 '15 19:10

Anwesha


People also ask

How do you release ownership of a shared pointer?

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 .

Can shared_ptr be copied?

The ownership of an object can only be shared with another shared_ptr by copy constructing or copy assigning its value to another shared_ptr . Constructing a new shared_ptr using the raw underlying pointer owned by another shared_ptr leads to undefined behavior.

Do I have to delete shared_ptr?

So no, you shouldn't. The purpose of shared_ptr is to manage an object that no one "person" has the right or responsibility to delete, because there could be others sharing ownership. So you shouldn't ever want to, either.

Can shared_ptr be Nullptr?

A null shared_ptr does serve the same purpose as a raw null pointer. It might indicate the non-availability of data. However, for the most part, there is no reason for a null shared_ptr to possess a control block or a managed nullptr .


1 Answers

You should not do that!

The standard library does not really facilitate such a move, going from std::unique_ptr to std::shared_ptr is always safe (because of the semantics of the two) — but the opposite is dangerous since there might be more owners of the resource than the particular std::shared_ptr you would like to move from.


No, really — do not do that!

I should probably tell you one more time, but I will assume that you are somewhat grown up and can stand accountable for your own decisions.


Ey, come on.. sure there is a hack for this?

If you would like to hack together a solution that would not be undefined-behavior unless the std::unique_ptr goes out of scope and you still have std::shared_ptrs that directly or indirectly end up using the resource.. you would probably end up with something like:

#include <memory>
namespace hack {
  struct conditional_deleter {
    void  disable () { _do_delete = false; }

    template<class T>
    void operator()(T* p) {
      if (_do_delete)
        delete p;
    }   

    bool _do_delete = true;
  };  
}
int main () {
  std::unique_ptr<int> up (new int (123));
  std::shared_ptr<int> sp (up.release (), hack::conditional_deleter {});
  std::shared_ptr<int> sb (sp);

  std::get_deleter<hack::conditional_deleter> (sp)->disable (); 
  std::unique_ptr<int> ub (sp.get ()); // see the name of this variable?
}                                      // can I get a ticket to UB-land, please?

WARNING

The above is far from recommended praxis, if you ever find yourself in a situation where you need such thing you should set fire to your workstation—probably your whole house—and work on a new program design.

like image 64
Filip Roséen - refp Avatar answered Sep 23 '22 17:09

Filip Roséen - refp