c++中如何使用smart pointers智能指针_c++ unique_ptr与shared_ptr用法


该用 std::unique_ptr 而不是 std::shared_ptr 的核心判断标准是所有权是否需要共享:unique_ptr 表示独占所有权,转移后原指针自动置空;shared_ptr 通过引用计数允许多方共享同一对象。

什么时候该用 std::unique_ptr 而不是 std::shared_ptr

核心判断标准是所有权是否需要共享:std::unique_ptr 表示独占所有权,转移后原指针自动置空;std::shared_ptr 通过引用计数允许多方共享同一对象。如果只是临时封装堆内存、函数返回资源、或作为容器元素管理单个对象,优先选 unique_ptr —— 它零开销、无原子操作、不引入循环引用风险。

常见误用场景:

  • shared_ptr 当作“更安全的 unique_ptr”随意传参,结果拖慢性能且掩盖设计问题
  • 在类成员中用 shared_ptr 管理本该由类自身生命周期决定的对象(比如内部缓存),导致对象存活时间超出预期
  • 跨线程传递 shared_ptr 但没意识到控制块(control block)的引用计数是原子操作,有轻微开销

unique_ptr 的正确构造与移动语义

unique_ptr 不支持拷贝,只支持移动。直接赋值或传参时若忘记 std::move(),编译器会报错:use of deleted function 'std::unique_ptr::unique_ptr(const std::unique_ptr&)'

推荐写法:

  • std::make_unique(...) 构造,避免裸 new 和异常安全问题
  • 函数返回 unique_ptr 时,直接 return std::make_unique(x);,调用方自动接收右值
  • 传入函数时,按值接收(void f(std::unique_ptr p)),表示函数要接管所有权;如只需观察,改用 T*T&
std::unique_ptr p1 = std::make_unique(42);
std::unique_ptr p2 = std::move(p1); // ✅ 正确:显式移动
// std::unique_ptr p3 = p1; // ❌ 编译失败

shared_ptr 的循环引用与 weak_ptr 解法

两个 shared_ptr 相互持有对方管理的对象(例如双向链表节点、父子对象关系),会导致引用计数永远不为 0,内存泄漏。这是 shared_ptr 最典型的陷阱。

解决方式不是少用 shared_ptr,而是识别“观测性引用”并替换为 std::weak_ptr

  • weak_ptr 不增加引用计数,调用 lock() 可尝试升级为 shared_ptr,失败说明对象已销毁
  • 典型模式:父持子用 shared_ptr,子持父用 weak_ptr
  • weak_ptr 本身不保证线程安全,但 lock() 是原子的
struct Node {
    std::shared_ptr next;
    std::weak_ptr prev; // 避免循环引用
};

auto a = std::make_shared();
auto b = std::make_shared();
a->next = b;
b->prev = a; // ✅ 不增加 a 的引用计数

自定义删除器与数组支持的细节差异

unique_ptrshared_ptr 都支持自定义删除器,但语法和默认行为不同:

  • unique_ptr 是合法类型,析构时自动调用 delete[];而 shared_ptr 在 C++17 前不被标准支持,C++17 起才允许,但仍需显式传入 default_delete
  • 自定义删除器类型是 unique_ptr 模板参数的一部分(影响类型),所以 unique_ptr != unique_ptr;而 shared_ptr 的删除器是运行期绑定的,类型不变
  • make_shared 无法指定自定义删除器,必须用裸 new + 构造函数方式
// unique_ptr 数组(推荐)
std::unique_ptr arr = std::make_unique(10);

// shared_ptr 数组(C++17+)
std::shared_ptr arr2(new int[10], std::default_delete());
真正难的不是记住语法,是每次写 shared_ptr 时多问一句:“这个对象,到底有没有别的地方也该负责它的生死?”——没想清楚就先用 unique_ptr


# node  # c++  # red  # 封装  # 构造函数  # const  # void  # 循环  # 指针  #   # 线程  # delete  # function  # 对象  # 自定义  # 该用  # 而不是  # 这是  # 一句  # 什么时候  # 只需  # 意识到  # 不支持  # 不为 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: Mac自带的词典App怎么用_Mac添加和使用多语言词典【技巧】  Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】  php下载安装后swoole扩展怎么安装_异步框架支持【汇总】  Win11怎么设置多显示器任务栏 Win11扩展任务栏至多屏方便跨屏操作【技巧】  Win11怎么设置默认浏览器Chrome_Windows11修改默认网页打开方式  Golang如何遍历目录文件_Golang filepath.Walk目录遍历操作方法  如何使用Golang配置安全开发环境_防止敏感信息泄露  XAMPP 启动失败(Apache 突然停止)的终极排查与修复指南  Windows执行文件被SmartScreen拦截原因_安全提示与绕过方式  Win11屏幕亮度突然变暗怎么解决_自动变暗问题处理  Win11怎么退出高对比度模式_Win11取消反色显示快捷键【修复】  Win10如何更改电脑休眠时间_Windows10电源和睡眠选项调整  c++ reinterpret_cast怎么用 c++最危险的类型转换【详解】  Windows10蓝屏SYSTEM_SERVICE_EXCEPTION_Win10驱动冲突排查  c# 在高并发下使用反射发射(Reflection.Emit)的性能  Win11怎么更改系统语言_Win11中文语言包下载与安装【指南】  如何在Golang中定义接口_抽象方法和多态实现  php怎么下载安装后测试是否成功_简单脚本验证方法【操作】  Win11怎么更改鼠标指针_Windows 11自定义鼠标样式与大小【美化】  如何使用Golang实现函数指针_函数变量与回调示例  Win10如何更改网络连接_Windows10以太网属性IP配置  C++如何使用std::optional?(处理可选值)  如何处理“XML格式不正确”错误 常见XML well-formed问题解决方法  c++中如何使用虚函数实现多态_c++多态性实现原理  Win11怎么关闭任务栏小组件_Windows11隐藏任务栏天气图标  php打包exe如何加密代码_防反编译保护方法【技巧】  Windows 10怎么隐藏特定更新补丁_Windows 10使用微软官方工具wushowhide.diagcab  php会话怎么开启_session_start函数的作用与使用时机【方法】  Win11怎么清理C盘下载文件夹_Win11清理下载文件夹技巧【教程】  零基础学会Python自动化办公_高效处理Excel与PDF文档  Win11怎么开启远程桌面连接_Windows11系统属性远程设置  php怎么操作Redis_Redis扩展连接与基本命令使用方法【方法】  如何使用正则表达式批量替换重复的星号-短横模式为固定字符串  Win11怎么关闭通知消息_屏蔽Windows 11右下角弹窗通知设置【详解】  Win11怎么关闭定位服务_保护Win11位置隐私设置指南【详解】  Win11怎么关闭系统透明度_Windows11个性化颜色透明效果  Windows 11怎么更改锁屏超时时间_Windows 11电源选项中设置屏幕关闭时间  Windows10如何更改桌面背景_Win10个性化幻灯片放映设置  Win11资源管理器卡顿怎么办 Win11文件资源管理器重启技巧【优化】  Win10怎样清理C盘Steam游戏缓存_Win10清理Steam游戏缓存步骤【步骤】  Windows10如何查看保存的WiFi密码_Win10命令行netsh wlan查询  Win11怎么开启游戏模式_Win11优化游戏帧数性能【教程】  php内存溢出怎么排查_php内存限制调试与优化方法【说明】  Python对象比较排序规则_集合使用说明【指导】  Python网络异常模拟_测试说明【指导】  Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件  php485返回数据不完整怎么办_php485数据分包重组处理方法【教程】  php控制舵机角度怎么调_php发送pwm信号控制舵机转动【解答】  Windows如何拦截腾讯视频广告_Windows拦截腾讯视频广告方法【方法】  如何在Golang中实现并发消息队列消费者_Golang channel消息消费实践 

 2026-01-01

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.