c ++ shared_ptr发布所有权

Anw*_*sha 5 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
Run Code Online (Sandbox Code Playgroud)

现在我想将指针的所有权转移s回去u.可悲的是,除此之外release() function in shared_ptr like in unique_ptr别无他法: -

u.reset(s.release());
Run Code Online (Sandbox Code Playgroud)

此外,这也无法奏效: -

u.reset(s.get());
Run Code Online (Sandbox Code Playgroud)

任何人都可以建议我如何转换shared_ptrunique_ptr或至少释放所拥有的指针shared_ptr

Fil*_*efp 12

你不应该这样做!

标准库并没有真正促进这一举措,从去std::unique_ptrstd::shared_ptr永远是安全的(因为这两个语义的) -但相反的是危险的,因为有可能是资源不是特定的更多的业主std::shared_ptr,你想从移动.


不,真的 - 不要那样做!

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


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

如果你想破解一个不会是未定义的解决方案- 行为,除非std::unique_ptr超出范围并且你仍然有std::shared_ptrs直接或间接最终使用资源...你可能最终得到类似的东西:

#include <memory>
Run Code Online (Sandbox Code Playgroud)
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;
  };  
}
Run Code Online (Sandbox Code Playgroud)
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?
Run Code Online (Sandbox Code Playgroud)

警告

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

  • 唯一安全的方法是订阅静态删除通知程序。通知程序可以通过共享指针的自定义删除器发出信号,然后通过订阅回调传递唯一指针......大量工作却没有任何收获。 (3认同)

Ank*_*rya 5

正如每个人都提到的,您无法转换shared_ptrunique_ptr,因为可能有多个人shared_ptr拥有该对象。因此没有release() functionfor shared_ptr。如果有一个 & 你会release()在一个shared_ptr对象上使用,当多个这样的对象共享资源时,那么其他shared_ptr指针对于它们是否拥有该资源就会产生歧义。

但是,因为您的实际问题是关于 of static& dynamic castingunique_ptr正如您在评论中提到的),所以我想补充一点,您实际上不需要使用shared_ptrfor casting unique_ptr& ,在这里我向您展示如何非常简单地做到这一点:-

void dynamic_unique_cast (unique_ptr<Parent> &pa)
{
    unique_ptr<Child> pb;    
    Parent *p=pa.release();   // release ownership
    try
    {
       pb.reset(dynamic_cast<Child*>(p));  // perform casting
       if (pb==nullptr)
       throw runtime_error {"nullptr exception"};
       cout<<"dynamic_cast successful\n\n";
       pa.reset(pb.release());  // if casting is successful then `pb` returns ownership back to `pa`
    }
    catch (exception &e)
    {
       cout<<"dynamic_cast unsuccessful: "<<e.what()<<"\n\n";
       pa.reset(p);  // if casting fails then `p` returns ownership to `pa`
    }
}
void static_unique_cast (unique_ptr<Parent> &pa)
{
    unique_ptr<Child> pb;
    Parent *p=pa.release();
    try
    {
       pb.reset(static_cast<Child*>(p));
       if (pb==nullptr)
       throw runtime_error {"nullptr exception"};
       show(pb);
       cout<<"static_cast successful\n\n";
       pa.reset(pb.release());
    }
    catch (exception &e)
    {
       cout<<"static_cast unsuccessful: "<<e.what()<<"\n\n";
       pa.reset(p);
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码运行得很好并且肯定会解决你的问题。如果您有任何歧义,请随时发表评论。

  • @FilipRoséen-refp:确实,这并没有回答原来的问题。OTOH 事实证明(从评论来看)OP 只是面临着 XY 问题。这篇文章确实回答了OP试图解决的真正问题(X),但没有提及。我同意,如果不阅读最后一条评论(默认情况下甚至没有展开),几乎不可能理解这个答案与问题的关系,但我很欣赏这个答案解决了 X 而不是 Y。 (2认同)