31

可能重复:
如何从 boost::shared_ptr 释放指针?

我的接口的一个函数返回一个指向对象的指针。用户应该拥有该对象的所有权。我不想返回 Boost.shared_ptr,因为我不想强迫客户使用 boost。但是,在内部,我想将指针存储在 shared_ptr 中,以防止出现异常等情况下的内存泄漏。似乎没有办法将指针与共享指针分离。这里有什么想法吗?

4

5 回答 5

27

您正在寻找的是一个release功能;shared_ptr没有释放功能。 根据 Boost 手册

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

A. shared_ptr 不能放弃所有权,除非它是 unique() 因为另一个副本仍然会破坏该对象。

考虑:

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类似共享指针并在您的外部接口上使用它。

您还可以查看有关在库的公共接口中使用 boost::shared_ptr 的这个问题的讨论。

于 2009-12-02T14:52:02.830 回答
25

总有办法:-)

他们不提供 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();
于 2011-05-13T17:45:40.383 回答
11

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

shared_ptr表示共享所有权,并且您希望您的界面表示所有权转移std::auto_ptr因此在这里更适用。

但是,在内部,我想将指针存储在 shared_ptr 中,以防止出现异常时发生内存泄漏

同样,shared_ptr可能不是该工作的最佳工具。在异常情况下防止泄漏,scoped_ptr否则auto_ptr会更适合。

于 2009-12-02T15:07:06.217 回答
6

使用 a shared_ptrto a to ascoped_ptr资源 ( shared_ptr<scoped_ptr<Resource>>)。这样你就可以得到shared_ptr的引用计数,当且仅当它仍然附加到scoped_ptr. 但是,scoped_ptr当您准备好移交所有权时,您可以将其分离。

于 2011-09-29T22:40:13.427 回答
2

正如 James 所介绍的那样,您不能真正分离共享指针。

您是否在内部需要多个所有者,或者您是否将所有权从您的班级转移给客户?在这种情况下,astd::auto_ptr可能符合要求。

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

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

于 2009-12-02T15:06:39.933 回答