views:

399

answers:

3

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?

+8  A: 

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.

James McNellis
Ok, feared it might be something like that.
Space_C0wb0y
shared_ptr is a bit like const keyword, add it in one place and you have to use it everywhere
Nikola Smiljanić
+2  A: 

As James has well covered you can't really detach a shared pointer.

Do you need multiple owners internally, or are you transferring ownership from your class to the client? In that case a std::auto_ptr might fit the bill.

If you're worried about the surprising semantics of std::auto_ptr, you could hold it internally by boost::scoped_ptr, and detach it at the point you hand it out - leaving it up to the client to manually delete it or store it in their own smart pointer.

If you do have multiple owners on your side you could use an intrusive count. Internally you could then use boost::intrusive__ptr, but hand off the raw pointer at the interface. The client can then either manually work with ref counts, or store it in a boost::intrusive_ptr themselves (but you don't make them depend on it)

Phil Nash
+3  A: 

The user is supposed to take ownership of that object. I do not want to return a Boost.shared_ptr,

shared_ptr expresses shared ownership, and you want your interface to express transfer of ownership. std::auto_ptr would thus be more applicable here.

Internally however, I would like to store the pointer in a shared_ptr to prevent memory leaks in case of exceptions

Again, shared_ptr may not be the best tool for that job. To prevent leaks in the case of exceptions, scoped_ptr or auto_ptr would be better suited.

Éric Malenfant