新闻中心
C++ shared_ptr循环引用问题_C++ weak_ptr用法与解决方案
shared_ptr循环引用指两个对象互相持有对方的shared_ptr,导致引用计数无法归零而内存泄漏;解决方法是将一方改为weak_ptr,打破循环,如父-子结构中子节点用weak_ptr回指,确保非拥有关系不延长生命周期。

在C++中,shared_ptr 是一种智能指针,用于自动管理动态分配对象的生命周期。它通过引用计数机制确保当最后一个 shared_ptr 被销毁时,其所指向的对象也会被自动释放。然而,在使用 shared_ptr 时,一个常见且容易忽视的问题是循环引用,这会导致内存泄漏。
什么是 shared_ptr 循环引用?
当两个或多个对象通过 shared_ptr 相互持有对方时,引用计数永远不会降为0,即使这些对象已经不再被外部使用。结果是它们所占用的内存无法被释放。
例如:两个类 A 和 B,A 中有一个 shared_ptr 指向 B,B 中也有一个 shared_ptr 指向 A:
struct B; // 前向声明
struct A {
std::shared_ptr<B> ptr;
~A() { std::cout << "A destroyed\n"; }
};
struct B {
std::shared_ptr<A> ptr;
~B() { std::cout << "B destroyed\n"; }
};
如果创建如下对象:
auto a = std::make_shared<A>(); auto b = std::make_shared<B>(); a->ptr = b; b->ptr = a;
此时,a 和 b 的引用计数都为2。即使 a 和 b 离开作用域,它们各自的析构函数也不会被调用——因为彼此还持有着 shared_ptr 引用,导致内存泄漏。
如何解决?使用 weak_ptr 打破循环
wea
k_ptr 是一种不增加引用计数的智能指针,它“弱”引用一个由 shared_ptr 管理的对象。它用于观察对象是否还存在,而不参与生命周期管理。
修改上面的例子:将其中一个方向的 shared_ptr 改为 weak_ptr,即可打破循环。
Kuwebs企业网站管理系统3.1.5 UTF8
酷纬企业网站管理系统Kuwebs是酷纬信息开发的为企业网站提供解决方案而开发的营销型网站系统。在线留言模块、常见问题模块、友情链接模块。前台采用DIV+CSS,遵循SEO标准。 1.支持中文、英文两种版本,后台可以在不同的环境下编辑中英文。 3.程序和界面分离,提供通用的PHP标准语法字段供前台调用,可以为不同的页面设置不同的风格。 5.支持google地图生成、自定义标题、自定义关键词、自定义描
1
查看详情
struct B;
struct A {
std::shared_ptr<B> ptr;
~A() { std::cout << "A destroyed\n"; }
};
struct B {
std::weak_ptr<A> ptr; // 使用 weak_ptr
~B() { std::cout << "B destroyed\n"; }
};
现在,B 不再持有 A 的强引用,因此不会阻止 A 被销毁。当 a 离开作用域后,A 的引用计数变为1(来自 b->ptr),但由于 weak_ptr 不影响计数,A 实际上可以被释放。一旦 A 被释放,a 对 B 的引用消失,B 的引用计数也归零,B 随即被销毁。
访问 weak_ptr 所指向的对象时,需要先检查对象是否仍然存在:
if (auto locked = b.ptr.lock()) {
// 使用 locked 访问 A 对象
std::cout << "A is still alive\n";
} else {
std::cout << "A has been destroyed\n";
}
lock() 方法返回一个 shared_ptr,如果原对象还活着;否则返回空 shared_ptr。也可以用 expired() 判断是否已过期,但推荐使用 lock(),因为它线程安全。
典型应用场景
weak_ptr 常用于以下场景:
- 父-子结构:父节点用 shared_ptr 管理子节点,子节点用 weak_ptr 回指父节点。
- 缓存系统:缓存表保存 weak_ptr,避免因缓存引用导致对象无法释放。
- 观察者模式:观察者列表使用 weak_ptr,防止目标对象因观察者持有强引用而无法销毁。
- 事件回调:回调中引用对象时,使用 weak_ptr 避免循环依赖。
基本上就这些。只要在可能形成闭环的地方,把非拥有关系的一方换成 weak_ptr,就能有效避免 shared_ptr 的循环引用问题。关键是理解:谁真正“拥有”对象,谁就用 shared_ptr;只是“观察”或“引用”的,就该用 weak_ptr。
以上就是C++ shared_ptr循环引用问题_C++ weak_ptr用法与解决方案的详细内容,更多请关注其它相关文章!
# 回调
# seo.chinaz.comn
# 武清区网站优化哪家好些
# 邢台网站推广工作室
# 营销手段推广案例范文
# 潍坊全网seo方案招聘
# 免费网站建设深圳
# 金阊网站优化方案
# 虎丘seo排名价格
# 闵行网站建设首页
# 盐山seo优化经验
# 客户端
# 循环引用
# 什么问题
# 是一种
# 自定义
# 递归
# 企业网站
# 管理系统
# 关键词
# red
# 作用域
# 解决方法
# c++
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
Golang如何优化内存分配与垃圾回收_Golang内存管理与GC优化实践
J*aScript实现单选按钮与关联输入框的联动禁用教程
蛙漫漫画官网在线入口 蛙漫全本漫画免费阅读平台
如何在 Excel Online 和 Google 表格中更改日期格式
Go语言中的*string:深入理解字符串指针
CSS布局:解决全屏元素100%尺寸与外边距导致的页面溢出问题
LINUX的I/O重定向是什么_深入理解LINUX中 >、>> 与 < 的区别
QQ邮箱官方网页版登录 QQ邮箱个人邮箱快速访问
c++ dfs和bfs代码 c++深度广度优先搜索算法
极速漫画官方主页网址 极速漫画漫画在线浏览官网链接
在React函数组件中利用原生HTML5进行邮箱地址验证
斑马英语APP如何开启夜间护眼阅读_斑马英语APP夜间模式与低蓝光设置教程
CSS如何设置hover状态颜色_hover伪类调整背景或文字颜色
Win11怎么设置鼠标指针速度_Win11提高鼠标指针精确度选项
知音漫客正版漫画平台_知音漫客官网账号登录
Win10如何恢复误删的快捷方式_Win10重建常用软件快捷方式
深入理解J*aScript中的B样条曲线与节点向量生成
ACG动漫手机版官网入口 手机ACG动漫APP在线观看正版
Go语言中JSON数据解析与字段访问教程
J*aScript中针对特定容器内图片动画的实现教程
J*aScript 字符串标签转换:使用正则表达式高效替换
Yandex免登录网页版地址 Yandex搜索引擎官方访问入口
内存疯狂猛猛涨价:主板销量直接腰斩!
在J*a中如何使用BigDecimal进行高精度计算_BigDecimal类应用指南
MAC怎么让Dock栏只显示当前运行的应用_MAC终端命令实现极简Dock栏
如何优雅地扩展SprykerGlue后端API授权逻辑,使用spryker/glue-backend-api-application-authorization-connector-extension
Safari怎么安装扩展程序 浏览器插件安装与管理方法【详解】
拼多多购物车商品数量无法修改如何处理 拼多多购物车操作优化方法
PostgreSQL海量数据高效导入策略:Python与Django实践指南
C++20的source_location是什么_C++在编译期获取源码位置信息用于日志和断言
Golang如何处理RPC请求负载均衡_Golang RPC请求负载均衡策略与实践
高德地图总提示网络异常怎么办 高德地图离线导航设置与网络排查方法
豆包手机助手发布技术预览版:直接嵌入手机系统!努比亚样机发售
QQ邮箱正确登录入口_QQ邮箱官方网站使用地址
拼多多赚钱渠道_拼多多收益来源
天猫双十一预售商品怎么退款_天猫双十一预售退款操作指南
UC浏览器如何安装插件 UC浏览器添加扩展程序详细教程【进阶】
PyTorch模型训练准确率不提升:诊断与修复常见指标计算错误
怎么在html里运行vbs脚本_html中运行vbs脚本方法【教程】
PDF文件体积过大处理_PDF压缩技巧详解
小猿搜题在线学习页面在哪_小猿搜题在线学习中心入口
C++如何打印当前代码行号与文件名_C++预定义宏FILE与LINE的使用
126邮箱账号注册 电脑版登录入口
支付宝碰一碰设备是REDMI手机吗 博主拆机辟谣:处理器、内存都不一样
如何在CSS中使用visited与link控制链接颜色_visited link伪类配合
俄罗斯搜索引擎Yandex指南 附2025年免登录官网入口
J*aScript:在map操作中高效处理空数组
汽水音乐网页版使用入口_汽水音乐电脑版播放指南
sublime怎么进行远程开发编辑_配置rsub/rmate实现sublime编辑服务器文件
AO3镜像入口大全 AO3网页版内容访问全集


2025-11-26
浏览次数:次
返回列表