我们都知道我们可以在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
所拥有的指针吗?
答案 0 :(得分:12)
标准库并没有真正促进这样的移动,从std::unique_ptr
到std::shared_ptr
始终是安全的(因为两者的语义) - 但相反是危险的,因为可能有更多资源的所有者,而不是您想要移动的特定std::shared_ptr
。
我应该再告诉你一次,但我会假设你有点长大,可以对你自己的决定负责。
如果您希望破解一个不会 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;肯定会解决你的问题。如果您有任何歧义,请随时发表评论。