c++;共享发布所有权 我们都知道,在C++中,我们可以很容易地将UnQuyQPTR转换成SyrdY-PTR。但是,如果我进行了这样的转换:- unique_ptr<X> u=make_unique<X>(); // X is some class shared_ptr<X> s=move(u); // this works of course

c++;共享发布所有权 我们都知道,在C++中,我们可以很容易地将UnQuyQPTR转换成SyrdY-PTR。但是,如果我进行了这样的转换:- unique_ptr<X> u=make_unique<X>(); // X is some class shared_ptr<X> s=move(u); // this works of course,c++,shared-ptr,unique-ptr,C++,Shared Ptr,Unique Ptr,此外,这也不起作用:- u.reset(s.get()); 有谁能建议我如何将shared\u ptr转换为unique\u ptr或至少释放shared\u ptr拥有的指针吗?你不应该这样做! 标准库并没有真正促进这样的移动,从std::unique_ptr到std::shared_ptr总是安全的(因为两者的语义)-但是相反的情况是危险的,因为资源的所有者可能比您想要从中移动的特定std::shared_ptr更多 不,真的-不要那样做! 我可能应该再告诉你一次,但我会假设你已经长大了

此外,这也不起作用:-

u.reset(s.get());
有谁能建议我如何将
shared\u ptr
转换为
unique\u ptr
或至少释放
shared\u ptr
拥有的指针吗?

你不应该这样做! 标准库并没有真正促进这样的移动,从
std::unique_ptr
std::shared_ptr
总是安全的(因为两者的语义)-但是相反的情况是危险的,因为资源的所有者可能比您想要从中移动的特定
std::shared_ptr
更多


不,真的-不要那样做! 我可能应该再告诉你一次,但我会假设你已经长大了,可以为自己的决定负责


哎呀,来吧。。肯定有黑客攻击吗? 如果您想拼凑出一个解决方案,除非
std::unique_ptr
超出范围,并且您仍然拥有直接或间接使用资源的
std::shared_ptr
,否则该解决方案不会是未定义的行为。。您可能会得到以下结果:

#include <memory>
#包括
名称空间黑客{
结构条件删除器{
void disable(){u do\u delete=false;}
模板
void运算符()(T*p){
如果(_do_删除)
删除p;
}   
bool\u do\u delete=true;
};  
}
int main(){
std::唯一的(新的int(123));
std::shared_ptr sp(up.release(),hack::conditional_deleter{});
std::共享的ptr sb(sp);
std::get_deleter(sp)->disable();
std::unique_ptr ub(sp.get());//是否看到此变量的名称?
}//请给我一张去乌布兰德的票好吗?
警告 以上所述与推荐的做法相去甚远,如果你发现自己需要这样的东西,你应该点燃你的工作站——可能是你的整个房子——并着手进行新的程序设计


好的,看了这些评论之后,我现在意识到您想要的是一个版本的
dynamic\u pointer\u cast
for
unique\u ptr
s

请记住,独特的PTR是很好的。。。独一无二,以下是答案:

注意,这个答案乍一看可能并不复杂,但我认为重要的是要记住,
unique\u ptr
s可以有自定义的删除程序。如果我们将unique_ptr动态强制转换为new-one,则必须跟随deleter,但如果不插入转换垫片,则传递到新unique_ptr的deleter的指针将是错误的类型

此代码不仅动态地将所有权移动到新的指针类型,而且还连接到正确的反向指针强制转换,以便当移动到
unique\u ptr
的对象最终超出范围时,正确的删除程序可以在正确的接口上删除该对象

#include <iostream>
#include <memory>

template<class Dest, class Source, class Deleter>
auto
make_proxy_deleter(std::unique_ptr<Source, Deleter>& source)
{
    return [original = source.get_deleter()](Dest* p) {
        original(dynamic_cast<Source*>(p));
    };
}

template<class Dest, class T, class Deleter>
auto
dynamic_cast_unique(std::unique_ptr<T, Deleter>&& source)
{
    auto proxy_deleter = make_proxy_deleter<Dest>(source);
    auto p = dynamic_cast<Dest*>(source.get());
    if (!p) {
        return std::unique_ptr<Dest, decltype(proxy_deleter)>(nullptr,
                                                              std::move(proxy_deleter));
        // or... throw std::invalid_argument("not convertible");
    }

    return std::unique_ptr<Dest, decltype(proxy_deleter)>(dynamic_cast<Dest*>(source.release()),
                                                          std::move(proxy_deleter));
}

struct A {
    virtual ~A() {};
};
struct B {
    virtual ~B() {};
};
struct C: A, B {};


using namespace std;

auto main() -> int
{
    auto pa = make_unique<C>();
    auto pb = dynamic_cast_unique<B>(std::move(pa));
    return 0;
}
#包括
#包括
模板
汽车
生成代理删除程序(标准::唯一源)
{
返回[original=source.get_deleter()](Dest*p){
原始(动态_-cast(p));
};
}
模板
汽车
动态\u强制转换\u唯一(std::唯一\u ptr&&source)
{
自动代理删除器=生成代理删除器(源);
auto p=dynamic_cast(source.get());
如果(!p){
返回std::unique_ptr(nullptr,
std::move(proxy_deleter));
//或者…抛出std::无效的_参数(“不可转换”);
}
返回std::unique_ptr(动态_cast(source.release()),
std::move(proxy_deleter));
}
结构A{
虚拟~A(){};
};
结构B{
虚拟~B(){};
};
结构C:A,B{};
使用名称空间std;
auto main()->int
{
自动pa=使_唯一();
自动pb=动态施法唯一(标准::移动(pa));
返回0;
}

正如大家所提到的,您不能将
共享\u ptr
转换为
唯一\u ptr
,因为可能有多个
共享\u ptr
拥有该对象。因此,
shared\u ptr
没有
release()函数。如果有一个&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;如果有一个&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;当其中一个

然而,因为您的实际问题是关于
独特的ptr
静态和动态转换
(正如您在评论中提到的),所以我想补充一点,您不需要实际使用
共享的ptr
来转换独特的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);
    }
}
void dynamic\u unique\u cast(unique\u ptr&pa)
{
独特的ptr-pb;
父*p=pa.release();//释放所有权
尝试
{
pb.reset(dynamic_cast(p));//执行强制转换
如果(pb==nullptr)
抛出运行时_错误{“nullptr异常”};

“你为什么要这么做?”当你已经有了一个
共享的\u ptr
时,
唯一的\u ptr
对afaics没有任何好处。一旦指针指向
共享的\u ptr
,它可以与更多的
共享的\u ptr
实例进一步共享。只释放其中一个不会有任何帮助。我怀疑这就是为什么没有机制来做到这一点。@AndreyNasonov很可能,该方法接受
unique\u ptr
,因为它拥有对象的所有权。但如果你手中只有
shared\u ptr
,那么所有权就不是你的了;其他人也可能共享它,而你也没有办法将它从他们手中夺走。@IgorTandetnik,我同意这不应该发生在设计良好的系统中。但是,如果
shared\u ptr
目前只有一个所有者,该怎么办?@Anwesha,当您对
shared\u ptr
应用静态和动态强制转换时,您将创建一个新的
s
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?
#include <iostream>
#include <memory>

template<class Dest, class Source, class Deleter>
auto
make_proxy_deleter(std::unique_ptr<Source, Deleter>& source)
{
    return [original = source.get_deleter()](Dest* p) {
        original(dynamic_cast<Source*>(p));
    };
}

template<class Dest, class T, class Deleter>
auto
dynamic_cast_unique(std::unique_ptr<T, Deleter>&& source)
{
    auto proxy_deleter = make_proxy_deleter<Dest>(source);
    auto p = dynamic_cast<Dest*>(source.get());
    if (!p) {
        return std::unique_ptr<Dest, decltype(proxy_deleter)>(nullptr,
                                                              std::move(proxy_deleter));
        // or... throw std::invalid_argument("not convertible");
    }

    return std::unique_ptr<Dest, decltype(proxy_deleter)>(dynamic_cast<Dest*>(source.release()),
                                                          std::move(proxy_deleter));
}

struct A {
    virtual ~A() {};
};
struct B {
    virtual ~B() {};
};
struct C: A, B {};


using namespace std;

auto main() -> int
{
    auto pa = make_unique<C>();
    auto pb = dynamic_cast_unique<B>(std::move(pa));
    return 0;
}
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);
    }
}