C++ 从 shared_ptr 中分离指针?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1833356/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:19:47  来源:igfitidea点击:

Detach a pointer from a shared_ptr?

c++boostshared-ptr

提问by Bj?rn Pollex

Possible Duplicate:
How to release pointer from boost::shared_ptr?

可能的重复:
如何从 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?

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

采纳答案by James McNellis

What you're looking for is a releasefunction; shared_ptrdoesn't have a release function. Per the Boost manual:

你要找的是一个release函数;shared_ptr没有释放功能。 根据 Boost 手册

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 不提供 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.

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.

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

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 orto 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.
  • 您可以使用std::tr1::shared_ptr,这将要求您的用户使用支持 TR1 的 C++ 库实现使用 Boost;至少这会让他们在两者之间做出选择。
  • 您可以实现自己的boost::shared_ptr类似共享指针,并在您的外部接口上使用它。

You might also look at the discussion at this question about using boost::shared_ptr in a library's public interface.

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

回答by Magnus

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):

他们不提供 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();

回答by éric Malenfant

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

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

shared_ptrexpresses sharedownership, and you want your interface to express transferof ownership. std::auto_ptrwould thus be more applicable here.

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

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

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

Again, shared_ptrmay not be the best tool for that job. To prevent leaks in the case of exceptions, scoped_ptror auto_ptrwould be better suited.

同样,shared_ptr可能不是该工作的最佳工具。以防万一出现泄漏,scoped_ptr还是auto_ptr比较适合的。

回答by Ben Voigt

Use a shared_ptrto a scoped_ptrto 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_ptrwhen you're ready to hand off ownership.

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

回答by philsquared

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

正如 James 已经很好地介绍的那样,您无法真正分离共享指针。

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

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

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.

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

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_ptrthemselves (but you don't make them depend on it)

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