Detach a pointer from a shared_ptr? [duplicate]

女生的网名这么多〃 提交于 2019-12-17 09:47:19

问题


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?


回答1:


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.




回答2:


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();



回答3:


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.




回答4:


Use a shared_ptr to a scoped_ptr to the resource (shared_ptr<scoped_ptr<Resource>>). That way you get shared_ptr's reference counting, which will automatically destroy the resource if and only if it's still attached to the scoped_ptr. But you can detach the scoped_ptr when you're ready to hand off ownership.




回答5:


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)



来源:https://stackoverflow.com/questions/1833356/detach-a-pointer-from-a-shared-ptr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!