资讯动态

通过std::unique_ptr初始化std::shared_ptr

发布时间:2026/10/8 12:05:41 来源:尧图企业网站定制
std::shared_ptr可从std::unique_ptr初始化通过移动语义实现所有权的单向降级独占转共享资源安全转移删除器被类型擦除后存入控制块。该设计允许接口解耦与延迟共享开销提升灵活性与性能是标准刻意支持的机制。一、标准规定了什么C 标准为std::shared_ptr提供了一个构造函数templateclass Y, class D shared_ptr(std::unique_ptrY, D r);关键点参数类型是右值引用​unique_ptr调用后r被置空不再拥有资源资源的所有权从unique_ptr转移给shared_ptr这意味着只有unique_ptr可以被“移动”给shared_ptr拷贝是不允许的。二、为什么允许所有权的单向降级所有权模型决定了这种转换的合法性模型语义unique_ptr我是唯一所有者我销毁资源shared_ptr我们是共同所有者最后一个销毁资源从独占到共享是所有权的降级原来一个人说了算现在交给一个群体共同管理。这在逻辑上完全自洽——资源依然存在只是释放时机从“当前作用域结束”变成了“最后一个shared_ptr析构”。反过来则不行从shared_ptr到unique_ptr意味着强行剥夺其他共享者的权利会导致悬垂指针和重复释放因此标准禁止。三、底层发生了什么std::unique_ptrFoo u std::make_uniqueFoo(); std::shared_ptrFoo s std::move(u);执行步骤接管指针s获得u内部管理的原始指针复制删除器u的删除器被复制到s的控制块中置空源对象u内部指针变为nullptr析构时不再做任何事初始化控制块s的强引用计数设为 1结果u变为空壳s成为资源的唯一管理者尽管它是共享指针但当前引用计数为 1。四、删除器如何被保留unique_ptrT, D的删除器是类型的一部分编译期确定。shared_ptrT的删除器是类型擦除的存储在控制块中。转换时shared_ptr把unique_ptr的删除器包装成一个类型无关的可调用对象存入控制块。因此即使shared_ptr的模板参数只有T它也能在引用计数归零时调用正确的删除逻辑。前提只有一个删除器必须可复制。五、为什么标准要提供这个能力1. 接口解耦工厂函数可以统一返回unique_ptr调用方按需决定是否共享std::unique_ptrFoo create(); // 库只负责创建 // 调用方 A不需要共享零开销 auto u create(); // 调用方 B需要共享 auto s std::shared_ptrFoo(create());如果只能返回shared_ptr所有调用方都要承担原子引用计数的开销即使他们不需要共享。2. 延迟共享开销局部作用域内用unique_ptr管理资源零开销直到真正需要跨作用域共享时才转为shared_ptrvoid f() { auto u std::make_uniqueFoo(); // 零开销 u-init(); if (need_share) { std::shared_ptrFoo s std::move(u); // 此时才引入共享开销 pass_to_other_thread(s); } }六、一句话总结shared_ptr可以从unique_ptr初始化是因为独占所有权可以通过移动语义安全地降级为共享所有权且删除器被完整保留在shared_ptr的控制块中。这是标准刻意设计的能力用于解耦资源创建与生命周期管理策略。不需要std::move也能编译是因为临时对象本身就是右值自动匹配移动构造函数。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑