Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detach a pointer from a shared_ptr? [duplicate]

Possible Duplicate:
How to release pointer from boost::shared_ptr?

A function of my interface returns a pointer to an object. The user is supposed to take ownership of that object. I do not want to return a Boost.shared_ptr, because I do not want to force clients to use boost. Internally however, I would like to store the pointer in a shared_ptr to prevent memory leaks in case of exceptions etc. There seems to be no way to detach a pointer from a shared pointer. Any ideas here?

like image 345
Björn Pollex Avatar asked Dec 02 '09 14:12

Björn Pollex


People also ask

Can you copy shared_ptr?

After you initialize a shared_ptr you can copy it, pass it by value in function arguments, and assign it to other shared_ptr instances.

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 .

Is copying shared_ptr thread safe?

When you copy a std::shared_ptr in a thread, all is fine. At first to (2). By using copy construction for the std::shared_ptr localPtr, only the control block is used. That is thread-safe.

What does shared_ptr get () do?

std::shared_ptr::getReturns the stored pointer. The stored pointer points to the object the shared_ptr object dereferences to, which is generally the same as its owned pointer.


2 Answers

What you're looking for is a release function; shared_ptr doesn't have a release function. Per the Boost manual:

Q. Why doesn't shared_ptr provide a release() function?

A. shared_ptr cannot give away ownership unless it's unique() because the other copy will still destroy the object.

Consider:

shared_ptr<int> a(new int); shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2  int * p = a.release();  // Who owns p now? b will still call delete on it in its destructor. 

Furthermore, the pointer returned by release() would be difficult to deallocate reliably, as the source shared_ptr could have been created with a custom deleter.

Two options you might consider:

  • You could use std::tr1::shared_ptr, which would require your users to use a C++ library implementation supporting TR1 or to use Boost; at least this would give them the option between the two.
  • You could implement your own boost::shared_ptr-like shared pointer and use that on your external interfaces.

You might also look at the discussion at this question about using boost::shared_ptr in a library's public interface.

like image 177
James McNellis Avatar answered Sep 30 '22 15:09

James McNellis


there's always a way :-)

There is indeed a reason why they don't provide a release() method, but it's not impossible to create one. Make your own deleter. Something on the line of (haven't actually compiled the code, but this is the general notion):

template <typename T> class release_deleter{ public:   release_deleter() : released_(new some_atomic_bool(false)){}   void release() {released_->set(true);}   void operator()(T* ptr){if(!released_->get()) delete ptr;} private:   shared_ptr<some_atomic_bool> released_; }  ..  shared_ptr<some_type> ptr(new some_type, release_deleter<some_type>());  ..  release_deleter<some_type>* deleter = get_deleter<release_deleter<some_type>>(ptr); deleter->release(); some_type* released_ptr = ptr.get(); 
like image 30
Magnus Avatar answered Sep 30 '22 14:09

Magnus