c ++ shared_ptr发布所有权

时间:2015-10-10 19:49:04

标签: c++ shared-ptr unique-ptr

我们都知道我们可以在C ++中轻松地将unique_ptr转换为shared_ptr。但是如果我做了这样的转换怎么办: -

unique_ptr<X> u=make_unique<X>();    // X is some class
shared_ptr<X> s=move(u);      // this works of course

现在我想将s中指针的所有权转回u。可悲的是,没有release() function in shared_ptr like in unique_ptr我可能不会有这样的事情: -

u.reset(s.release());

此外,这也无法奏效: -

u.reset(s.get());

有人可以建议我如何将shared_ptr转换为unique_ptr或至少释放shared_ptr所拥有的指针吗?

3 个答案:

答案 0 :(得分:12)

你不应该这样做!

标准库并没有真正促进这样的移动,从std::unique_ptrstd::shared_ptr始终是安全的(因为两者的语义) - 但相反是危险的,因为可能有更多资源的所有者,而不是您想要移动的特定std::shared_ptr

不,真的 - 不要那样做!

我应该再告诉你一次,但我会假设你有点长大,可以对你自己的决定负责。

Ey,来吧..确定有这个黑客?

如果您希望破解一个不会 undefined-behavior 的解决方案,除非std::unique_ptr超出范围并且您仍然直接或间接拥有std::shared_ptrs最终使用资源..你最终会得到类似的东西:

#include <memory>
namespace hack {
  struct conditional_deleter {
    void  disable () { _do_delete = false; }

    template<class T>
    void operator()(T* p) {
      if (_do_delete)
        delete p;
    }   

    bool _do_delete = true;
  };  
}
int main () {
  std::unique_ptr<int> up (new int (123));
  std::shared_ptr<int> sp (up.release (), hack::conditional_deleter {});
  std::shared_ptr<int> sb (sp);

  std::get_deleter<hack::conditional_deleter> (sp)->disable (); 
  std::unique_ptr<int> ub (sp.get ()); // see the name of this variable?
}                                      // can I get a ticket to UB-land, please?
  

警告

     

以上内容远非推荐的实践,如果你发现自己处于需要这样的事情的情况下,你应该放火烧你的工作站 - 可能是你的整个房子 - 并开展新的程序设计。

答案 1 :(得分:2)

好的,看过评论我现在意识到你想要的是dynamic_pointer_cast的{​​{1}}版本。

记住unique_ptrs很好......唯一,这就是答案:

请注意,这个答案乍一看似乎不一定很复杂,但我认为记住unique_ptr可以有自定义删除器很重要。如果我们动态地将unique_ptr转换为新的,则删除器必须遵循,但是如果没有插入翻译垫片,则传递给新的unique_ptr删除器的指针将是错误的类型。

此代码不仅动态地将所有权移动到新的指针类型,而且还连接正确的反向指针,以便在移动到unique_ptr时正确的删除器可以在正确的接口上删除对象终于超出了范围。

unique_ptr

答案 2 :(得分:1)

正如大家所提到的,您无法将shared_ptr转换为unique_ptr,因为多个shared_ptr可能拥有该对象。因此release() function没有shared_ptr。曾经有一个&amp;你会在一个release()对象上使用shared_ptr当多个这样的对象共享一个资源时,那么其他shared_ptr指针关于它们是否拥有该资源会有歧义

但是,因为您的实际问题与static& dynamic casting的{​​{1}}有关(正如您在评论中提到的那样)所以我想补充一点,您无需实际使用unique_ptr shared_ptr&amp;在这里,我告诉你如何做到这一点非常简单: -

casting unique_ptr

以上代码效果很好&amp;肯定会解决你的问题。如果您有任何歧义,请随时发表评论。