当前位置: 首页 > 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.dtcms.com/a/273433.html

相关文章:

  • 传输层协议UDP原理
  • 秋招小白学数据结构-1-数据结构前置知识
  • C Primer Plus 第6版 编程练习——第9章(上)
  • Umi-OCR 的 Docker(win制作镜像,Linux(Ubuntu Server 22.04)离线部署)
  • 微软语音合成标记语言SSML文档结构和事件(详细文档和实例)
  • 企业级配置:Azure 邮件与 Cloudflare 域名解析的安全验证落地详解
  • Unity Demo——3D平台跳跃游戏笔记
  • 一个与运行 Qwen3 大语言模型的 vLLM 服务进行通信的客户端程序
  • 利用BeautifulSoup解析大众点评区域店铺网页
  • WHQL认证失败怎么办?企业如何高效申请
  • 云、实时、时序数据库混合应用:医疗数据管理的革新与展望(上)
  • https——TCP+TLS
  • ChatGPT无法登陆?分步排查指南与解决方案
  • S7-1200 与 S7-300 CPS7-400 CP UDP 通信 Step7 项目编程
  • MS1826+MS9332 4K@30Hz HD4×2视频分割器
  • .net服务器Kestrel配置Nginx作为反向代理
  • 如何准确查看服务器网络的利用率?
  • 如何查看自己本地的公网IP地址?内网环境网络如何开通服务器公网ip提供互联网访问?
  • UDP服务器的优缺点都包含哪些?
  • Spring Boot主从服务器详解教程
  • 性能狂飙 Gooxi 8卡5090服务器重新定义高密度算力
  • 中国银联豪掷1亿采购海光C86架构服务器
  • 没有管理员权限,在服务器安装使用 Jupyter + R 内核
  • JVM 内存结构
  • QTextCodec的功能及其在Qt5及Qt6中的演变
  • RLHF(人类反馈的强化学习)
  • Java JDK 下载指南
  • ThinkBook 14s IWL(20RM)OEM系统镜像原厂Win10系统
  • Zero-Shot(零样本学习),One-Shot(单样本学习),Few-Shot(少样本学习)概述
  • CVE-2023-41990/CVE-2023-32434/CVE-2023-38606/CVE-2023-32435