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

C++——智能指针 weak_ptr

weak_ptr这个指针天生一副小弟的模样,也是在C++11的时候引入的标准库,它的出现完全是为了弥补它老大shared_ptr天生有缺陷的问题。只能配合shared_ptr一起使用

shared_ptr循环引用造成的后果:存在资源泄露

一、shared_ptr 的循环引用

什么是循环引用的问题呢?在shared_ptr的使用过程中,当强引用计数为0时,就会释放所指向的堆内存。那么问题来了,如果和死锁一样,当两个shared_ptr互相引用,那么它们就永远无法被释放了。

循环引用指的是两个或者多个对象互相持有对方的’std::shared_ptr‘使得引用计数永远不会将为0,从而导致资源无法释放

struct ListNode { int _data; shared_ptr<ListNode> _prev; shared_ptr<ListNode> _next; ~ListNode() { cout << "~ListNode()" << endl; } }; int main() { shared_ptr<ListNode> node1(new ListNode); shared_ptr<ListNode> node2(new ListNode); node1->_next = node2; node2->_prev = node1; return 0; }

以上代码运行,检测到如下内存泄露:

分析:定义出来的sp1和sp2都有如下的结构, 首先sp1是一个智能指针shared_ptr,所以它有它的_ptr和_pCount字段,其次ListNode结构的结点内部有三个成员变量,分别为data next prev,而且这个next和prev它俩也是俩个shared_ptr智能指针对象,也有其自己的_ptr和_pCount,于是定义出来的sp1对象就有如下的结构。sp2结构也和此图一致。

经过如下的链接操作后:形成如下图的链接结构。

node1->_next = node2; node2->_prev = node1;

随后,程序执行结束,进入到对象的析构环节,后创建的元素先析构,先进行sp2对象的析构,根据shared_ptr计数功能,对右边计数器进行--操作,发现计数器无法归零,所以不能对sp2资源进行释放,转而进行sp1对象的析构处理,但是对左侧计数器进行--操作后,发现仍然不能归零,俩个对象中的next和prev分别造成了不同计数器的无法归零,就导致内存泄露,资源无法回收。

二、weak_ptr 解决循环引用

标准库提供了weak_ptr,唯一作用就是帮助shared_ptr解决循环引用的问题

weak_ptr不能管理资源,只能配合shared_ptr一起使用。

如此修改之后,俩个对象正常进行析构,并且没有产生资源泄露。

三、为什么weak_ptr能解决这个问题?

weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数

可以看到上图的代码运行结果,打印出来的就是sp1和sp2俩个对象的引用计数,发现在进行next和pre指针的指向链接后,并没有对sp1和sp2对象的引用计数更改。

weak_ptr的原理

weak_ptr是为了配合shared_ptr而引入的一种智能指针,它指向一个由shared_ptr管理的对象而不影响所指对象的生命周期,也就是,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。不论是否有weak_ptr指向,一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。从这个角度看,weak_ptr更像是shared_ptr的一个助手而不是智能指针。

实际shared_ptr源码中存在俩个变量来进行计数,一个是use_count 一个是weak_count ,它俩的初始化均为1,use也就是我们之前一直打印出来的当前对象有关联的对象计数个数,而weak就是这个shared_ptr指针所管理的资源weak_ptr类型的变量个数。下图即为,在next和prev连接后的结果图,此时use_count均为1,weak_ptr均为2;

http://www.jsqmd.com/news/800199/

相关文章:

  • 终极指南:3大微服务性能测试工具对比(JMeter vs Gatling vs k6)
  • 从‘古董’工具Cain看网络安全演进:当年的ARP欺骗与密码嗅探,今天还管用吗?
  • claude-recall:为AI编程助手赋予记忆,自动化你的重复工作流
  • 解决汉化在线版加载后显示英文问题的技术分析
  • 5个方法掌握FModel:解锁虚幻引擎游戏资源的终极指南
  • Free List Allocator实现原理:memory-allocators中的通用内存分配器
  • 网盘直链下载助手:技术实现与高级使用指南
  • 从CTFHub靶场实战,聊聊JWT那些容易被忽略的安全坑(附工具和脚本)
  • NCRF++模型对比分析:CharLSTM vs CharCNN vs WordLSTM性能测评终极指南
  • Vidispine Hull镜像:快速搭建企业级媒体资产管理开发测试环境
  • 3分钟解锁AI图像分层魔法:layerdivider让复杂设计变简单
  • 高级内存管理技巧:从memory-allocators中学到的10个最佳实践
  • 超节点大单交付公告时连续中标背后的“隐性护城河”
  • Agent:它不是更聪明的大模型,而是让大模型持续推进任务的“大脑+身体”系统!
  • element plus el-table 修改表格边框颜色
  • 往复式升降机厂家哪家好?2026年口碑好的往复式提升机厂家推荐:金拓机械设备领衔 - 栗子测评
  • ScispaCy项目架构深度剖析:从核心组件到扩展机制
  • 如何用DevPod快速搭建高性能大数据处理环境:完整指南
  • 移动端优化gh_mirrors/ti/til:PWA渐进式Web应用开发的终极指南
  • HealthGPT本地LLM部署教程:使用Llama3 8B模型的完整步骤
  • 达梦数据库安全加固实战:手把手教你配置密码策略和登录限制(含安全版/非安全版差异)
  • 从罗比到T-1000:影史三大机器人角色评选与技术启示
  • 2026年4月冷热冲击试验箱品牌口碑推荐,冷热冲击试验箱/高低温试验箱/三综合试验箱,冷热冲击试验箱供应商推荐 - 品牌推荐师
  • 构建个人技能仓库:Git+Markdown打造可复用的知识资产体系
  • 使用Create-MCP快速构建AI服务器:从协议原理到工程实践
  • 螺旋机厂家哪家靠谱?2026年优质螺旋提升机厂家|螺旋式提升机厂家盘点与推荐:金拓机械设备领衔 - 栗子测评
  • BLE Beacon技术原理与应用开发指南
  • 如何使用pretty-ts-errors:TypeScript错误追踪与性能优化终极指南
  • Apaxy深度定制教程:从零开始创建个性化主题
  • ComfyUI-Inpaint-Nodes深度解析:专业级图像修复工作流构建指南