当前位置: 首页 > news >正文

【C/C++ shared_ptr 和 unique_ptr可以互换吗?】

在 C++ 中,std::shared_ptrstd::unique_ptr 是两种不同的智能指针,它们有不同的所有权语义,不能直接互换,但在特定条件下可以相互转换:

1. unique_ptrshared_ptr (✅ 安全)

// unique_ptr 可以转换为 shared_ptr(移动语义)
std::unique_ptr<MyClass> unique = std::make_unique<MyClass>();
std::shared_ptr<MyClass> shared = std::move(unique); // 所有权转移// 此时 unique 变为 nullptr
assert(unique == nullptr);

2. shared_ptrunique_ptr (❌ 不安全)

std::shared_ptr<MyClass> shared = std::make_shared<MyClass>();
// 以下转换是无效的!会编译错误
std::unique_ptr<MyClass> unique = shared; // 错误:没有转换函数

3. 特殊情况:当 shared_ptr 是唯一所有者时

if (shared.use_count() == 1) {// 危险操作:手动释放所有权(不推荐)MyClass* raw = shared.get();shared.reset(); // 放弃所有权std::unique_ptr<MyClass> unique(raw); // 接管所有权
}

⚠️ 警告:这种操作非常危险,容易导致双重释放!


关键区别:

特性std::unique_ptrstd::shared_ptr
所有权独占所有权共享所有权
复制语义不可复制(只能移动)可以复制
性能开销零开销(等同原始指针)有引用计数开销
循环引用风险需要配合 weak_ptr 避免
自定义删除器支持(类型安全)支持(类型擦除)

最佳实践:

  1. 优先使用 unique_ptr

    // 默认使用 unique_ptr
    auto resource = std::make_unique<Resource>();// 需要共享时再转换
    std::shared_ptr<Resource> shared_res = std::move(resource);
    
  2. 需要共享所有权时直接用 shared_ptr

    // 明确需要共享的场景
    auto shared = std::make_shared<SharedResource>();
    
  3. 避免所有权混用
    同一资源不应同时被两种智能指针管理。

转换工具函数(C++17+):

// unique_ptr → shared_ptr
template<typename T>
std::shared_ptr<T> make_shared_from_unique(std::unique_ptr<T>&& unique) {return std::shared_ptr<T>(std::move(unique));
}// shared_ptr → unique_ptr (危险!仅用于特殊情况)
template<typename T>
std::unique_ptr<T> make_unique_from_shared(std::shared_ptr<T> shared) {if (shared.use_count() != 1) throw std::logic_error("Not exclusive owner!");return std::unique_ptr<T>(shared.release()); // 需要自定义删除器支持
}

结论:

  1. unique_ptrshared_ptr:✅ 安全,通过移动语义实现
  2. shared_ptrunique_ptr:❌ 不安全,应避免
  3. 设计时应明确所有权策略,避免混用
  4. 当需要共享所有权时,直接从源头使用 shared_ptr
http://www.lryc.cn/news/585371.html

相关文章:

  • 【AI News | 20250710】每日AI进展
  • 一个中层管理者应该看什么书籍?
  • 使用Python将目录中的JPG图片按后缀数字从小到大顺序纵向拼接,很适合老师发的零散图片拼接一个图片
  • 谷歌独立站是什么?谷歌独立站建站引流完全指南
  • HarmonyOS基础概念
  • Python中类静态方法:@classmethod/@staticmethod详解和实战示例
  • C#中的设计模式:构建更加优雅的代码
  • 链接代理后无法访问网络
  • C++入门基础篇(二)
  • HandyJSON使用详情
  • 使用Spring Boot和PageHelper实现数据分页
  • Excel快捷键
  • 20250710-2-Kubernetes 集群部署、配置和验证-网络组件存在的意义?_笔记
  • leetcode:377. 组合总和 Ⅳ[完全背包]
  • 代账行业数字化破局:从“知道”到“做到”,三步走稳赢!
  • RK3566/RK3568 Android11 修改selinux模式
  • 森马服饰从 Elasticsearch 到阿里云 SelectDB 的架构演进之路
  • 【牛客刷题】超级圣诞树(递归法和分形复制法)
  • TCP服务器与客户端三种方法实现
  • Java使用OSHI获取服务器信息
  • 网络安全基础作业
  • python学习DataFrame数据结构
  • 无锁队列:从零构建生产者-消费者数据结构
  • 第十七节:第三部分:网络通信:UDP通信,一发一收,多发多收
  • 汽车级MCU选型新方向:eVTOL垂桨控制监控芯片的替代选型技术分析
  • aaa认证
  • lora网关
  • 如何选择数据可视化工具?从设计效率到图表表现力全解读
  • OD(OllyDbg)使用介绍
  • day02-数组part02