从shared_ptr中分离指针?

时间:2009-12-02 14:47:39

标签: c++ boost shared-ptr

  

可能重复:
  How to release pointer from boost::shared_ptr?

我的界面的一个功能返回一个指向对象的指针。用户应该拥有该对象的所有权。我不想返回Boost.shared_ptr,因为我不想强制客户端使用boost。但是,在内部,我想将指针存储在shared_ptr中以防止在异常等情况下发生内存泄漏。似乎无法从共享指针中分离指针。这里有什么想法吗?

5 个答案:

答案 0 :(得分:25)

您正在寻找的是release功能; shared_ptr没有发布功能。 Per the Boost manual

  

Q值。为什么shared_ptr不提供release()函数?

     

一个。 shared_ptr不能放弃所有权,除非它是唯一的(),因为另一个副本仍将销毁该对象。

     

考虑:

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.
  

此外,release()返回的指针很难可靠地解除分配,因为源shared_ptr可能是使用自定义删除器创建的。

您可以考虑两个选项:

  • 您可以使用std::tr1::shared_ptr,这将要求您的用户使用支持TR1 的C ++库实现来使用Boost;至少这会给他们两者之间的选择。
  • 您可以实现自己的boost::shared_ptr - 就像共享指针一样,并在外部接口上使用它。

您还可以查看有关using boost::shared_ptr in a library's public interface的问题的讨论。

答案 1 :(得分:24)

总有办法: - )

确实有一个原因,他们不提供release()方法,但创建一个并不是不可能的。制作自己的删除者。有些东西(实际上没有编译代码,但这是一般概念):

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

答案 2 :(得分:11)

  

用户应该拥有该对象的所有权。我不想返回Boost.shared_ptr,

shared_ptr表示共享所有权,并且您希望您的界面表达传输所有权。因此std::auto_ptr更适用于此。

  

在内部,我想将指针存储在shared_ptr中,以防止在异常情况下发生内存泄漏

同样,shared_ptr可能不是这项工作的最佳工具。为了防止异常情况下的泄漏,scoped_ptrauto_ptr会更适合。

答案 3 :(得分:4)

使用shared_ptrscoped_ptr资源(shared_ptr<scoped_ptr<Resource>>)。这样你得到shared_ptr的引用计数,当且仅当它仍然附加到scoped_ptr时,它将自动销毁资源。但是,当您准备交出所有权时,您可以分离scoped_ptr

答案 4 :(得分:2)

正如詹姆斯所涵盖的那样,你无法真正分离共享指针。

您是否需要内部多个所有者,或者您是否将所有权从您的班级转移到客户?在这种情况下,std::auto_ptr可能适合该法案。

如果您担心std::auto_ptr令人惊讶的语义,您可以在boost::scoped_ptr内部保留它,并在您交出时将其分离 - 将其留给客户端进行手动删除它或将其存储在自己的智能指针中。

如果你身边有多个拥有者,你可以使用侵入性计数。在内部,您可以使用boost::intrusive__ptr,但在接口处切换原始指针。然后客户端可以手动处理引用计数,或者将它自己存储在boost::intrusive_ptr中(但不要让它们依赖它)