该用 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。
推荐写法:
std::make_unique(...) 构造,避免裸 new 和异常安全问题unique_ptr 时,直接 return std::make_unique(x); ,调用方自动接收右值void f(std::unique_ptr p) ),表示函数要接管所有权;如只需观察,改用 T* 或 T&
std::unique_ptrp1 = 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_ptr 和 shared_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
致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。