我的接口的一个函数返回一个指向对象的指针。用户应该拥有该对象的所有权。我不想返回 Boost.shared_ptr,因为我不想强迫客户使用 boost。但是,在内部,我想将指针存储在 shared_ptr 中,以防止出现异常等情况下的内存泄漏。似乎没有办法将指针与共享指针分离。这里有什么想法吗?
5 回答
您正在寻找的是一个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 的这个问题的讨论。
总有办法:-)
他们不提供 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();
用户应该拥有该对象的所有权。我不想返回 Boost.shared_ptr,
shared_ptr
表示共享所有权,并且您希望您的界面表示所有权转移。std::auto_ptr
因此在这里更适用。
但是,在内部,我想将指针存储在 shared_ptr 中,以防止出现异常时发生内存泄漏
同样,shared_ptr
可能不是该工作的最佳工具。在异常情况下防止泄漏,scoped_ptr
否则auto_ptr
会更适合。
使用 a shared_ptr
to a to ascoped_ptr
资源 ( shared_ptr<scoped_ptr<Resource>>
)。这样你就可以得到shared_ptr
的引用计数,当且仅当它仍然附加到scoped_ptr
. 但是,scoped_ptr
当您准备好移交所有权时,您可以将其分离。
正如 James 所介绍的那样,您不能真正分离共享指针。
您是否在内部需要多个所有者,或者您是否将所有权从您的班级转移给客户?在这种情况下,astd::auto_ptr
可能符合要求。
如果您担心 令人惊讶的语义std::auto_ptr
,您可以在内部保存它boost::scoped_ptr
,并在您分发它时将其分离 - 让客户端手动删除它或将其存储在他们自己的智能指针中。
如果您身边确实有多个所有者,则可以使用侵入式计数。然后您可以在内部使用boost::intrusive__ptr
,但在接口处传递原始指针。然后,客户端可以手动使用引用计数,或者将其存储在boost::intrusive_ptr
自己中(但您不要让它们依赖它)