新闻中心

C++ shared_ptr怎么解决循环引用_C++智能指针使用与循环引用解决方案

2025-11-16
浏览次数:
返回列表
循环引用指两个对象的shared_ptr相互持有,导致引用计数无法归零而内存泄漏;解决方法是用weak_ptr打破闭环,如父节点用shared_ptr,子节点用weak_ptr指向父节点,避免析构失败。

c++ shared_ptr怎么解决循环引用_c++智能指针使用与循环引用解决方案

使用 shared_ptr 时,循环引用是一个常见问题,尤其在涉及双向关系的场景中,比如父子节点、观察者模式等。当两个对象通过 shared_ptr 相互持有对方时,引用计数无法归零,导致内存泄漏。

什么是循环引用?

假设有两个类 A 和 B,A 中有一个 shared_ptr,B 中也有一个 shared_ptr。如果它们相互赋值并形成闭环:

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。离开作用域后,各自释放一次,引用计数变为 1,但不会调用析构函数,造成内存泄漏。

使用 weak_ptr 打破循环

weak_ptr 是专门设计用来解决这个问题的智能指针。它不增加引用计数,只是“观察” shared_ptr 管理的对象。

修改上面的例子,把其中一个方向改为 weak_ptr

struct B {
    std::weak_ptr<A> ptr;  // 改为 weak_ptr
    ~B() { std::cout << "B destroyed\n"; }
};

这样,B 持有的是 A 的弱引用,不会增加其引用计数。当 a 离开作用域,A 的引用计数减到 0,被正确销毁;随后 b 销毁,B 也被释放。

Zyro AI Background Remover Zyro AI Background Remover

Zyro推出的AI图片背景移除工具

Zyro AI Background Remover 145 查看详情 Zyro AI Background Remover

访问 weak_ptr 时需先检查对象是否还存在:

if (auto locked = b.ptr.lock()) {
    // 使用 locked(返回 shared_ptr)
} else {
    // 对象已被释放
}

实际使用建议

在设计类关系时,明确“所有权”:

  • shared_ptr 表示共享所有权或强引用
  • weak_ptr 表示非拥有型引用,如父-子结构中的反向指针、缓存、观察者列表等
  • 避免两个 shared_ptr 在没有外部干预的情况下互相持有

例如,在树结构中,父节点用 shared_ptr 指向子节点,子节点用 weak_ptr 指向父节点,这样能安全释放整棵树。

基本上就这些。只要在可能形成闭环的地方主动用 weak_ptr 断开一环,就能有效防止循环引用。不复杂但容易忽略。

以上就是C++ shared_ptr怎么解决循环引用_C++智能指针使用与循环引用解决方案的详细内容,更多请关注其它相关文章!


# 已被  # 朔州推广网站建设  # 做网站建设哪个公司好  # 广元抖音关键词排名优化  # 丹棱县推广营销中心  # 如何看待网站推广  # 盐城网站建设哪家效果好  # 沈阳seo优化思路  # 招商网站建设及优化  # 国外seo都在做什么  # 怎样推广网站链接商品  # 中有  # c++  # 就能  # 是一个  # 的是  # 正确处理  # 如何处理  # 尼克  # 闭环  # red  # 作用域  # 常见问题  # 解决方法 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: J*a最大堆Heapify方法修复:索引计算与边界条件深度解析  win11 arm版怎么安装 M1/M2 Mac虚拟机安装ARM win11的方法  2306选座时如何选靠窗位置_12306选座靠窗座位查看方法解析  excel如何生成目录 excel一键生成工作表目录超链接  最新韩小圈网页版登录入口_官网在线观看官方链接  Django表单验证失败时保留用户输入数据的最佳实践  解决深度学习模型训练初期异常高损失与完美验证准确率问题  在哪找SublimeJ远程工具_SFTP插件配置教程  Python异步编程实践:使用Binance API构建实时交易数据流  Excel如何用迷你图显趋势_Excel用迷你图显趋势【趋势小图】  一加 14R 快充无反应_一加 14R 充电优化  2026年CSGO开箱网站推荐 CSGO开箱平台精选  处理嵌套交互式控件:前端可访问性指南  Python多版本共存与虚拟环境管理深度指南  怎样使用“本地安全策略”提升Windows安全性_Secpol.msc配置指南【高手】  如何在CSS中使用visited与link控制链接颜色_visited link伪类配合  动漫共和国防屏蔽稳定域名-动漫共和国官方正版直达通道  qq游戏大厅官方下载_qq游戏免费下载安装入口  在J*a里如何理解依赖关系的方向_依赖方向在模块结构中的作用  钉钉视频会议声音异常如何处理 钉钉会议音频修复技巧  C++如何实现线程池_C++11手动实现一个简单的固定大小线程池  4399体育竞技小游戏_4399小游戏赛事入口  单12V-2&#215;6实现为RTX 5090供电750W!甚至都没敢跑分  生成rdflib自定义SPARQL函数:参数匹配与实践指南  Win11如何开启讲述人功能 Win11屏幕阅读器(讲述人)开启与关闭【教程】  使用Python高效删除Word宏并转换DOCM为DOCX格式  小红书商家版怎样在笔记嵌入商品卡路径_小红书商家版在笔记嵌入商品卡路径【挂载教程】  UE5.7引擎表现爆炸优化无敌!5090跑4K稳定60FPS  谷歌浏览器最新官方入口链接 谷歌浏览器网页版官网导航  Surface怎么安装系统 微软Surface Pro U盘重装win11教程  汽车之家官方网站官网入口_汽车之家网页版直接进入  Python大型XML文件高效流式解析教程  Yandex官方入口网址 Yandex俄罗斯搜索引擎最新在线地址  Yandex浏览器官方网页版入口 Yandex浏览器最新版官网  怎样在Excel中做仪表盘_Excel仪表盘设计与关键指标展示方法  蛙漫正版漫画平台入口_蛙漫免费阅读全站漫画资源  qq邮箱日历功能怎么用_创建日程与会议邀请的技巧  c++中的const_cast和reinterpret_cast怎么用_c++四种类型转换  谷歌浏览器如何快速清除某个网站的数据_Chrome网站缓存清理方法  QQ邮箱网页版登录入口 QQ邮箱官方在线使用平台  J*a TimerTask中HashMap意外清空的深层原因与解决方案  抖音网页版平台入口 抖音网页版官网在线访问教程  Excel Power Pivot如何处理XML数据源 构建高级数据模型  豆包手机助手发布技术预览版:直接嵌入手机系统!努比亚样机发售  淘宝支付提示失败如何解决 淘宝支付流程优化方法  QQ邮箱稳定登录入口_QQ邮箱官方网站网页版使用  妖精漫画网页版登录入口免费_妖精漫画官网主页直接阅读漫画  J*aScript设计模式实践_j*ascript代码优化  React/Next.js中实现列表项的动态选择与移动  海棠账号登录入口_登录海棠账户同步阅读记录 

搜索