0

0

c++中shared_ptr如何解决循环引用的问题_c++ weak_ptr在智能指针循环依赖中的作用

下次还敢

下次还敢

发布时间:2025-10-17 14:07:02

|

256人浏览过

|

来源于php中文网

原创

使用 weak_ptr 可打破 shared_ptr 的循环引用。在双向关联中,一方用 shared_ptr,另一方用 weak_ptr,避免引用计数无法归零,确保对象正确析构,防止内存泄漏。

c++中shared_ptr如何解决循环引用的问题_c++ weak_ptr在智能指针循环依赖中的作用

在C++中,shared_ptr 是一种基于引用计数的智能指针,能自动管理动态分配对象的生命周期。当多个 shared_ptr 指向同一对象时,引用计数增加;当指针被销毁或重置时,引用计数减少;计数为0时,对象自动释放。

但使用 shared_ptr 时容易出现循环引用问题,导致内存无法释放。例如两个对象互相持有对方的 shared_ptr,即使外部不再使用它们,引用计数也不为零,造成内存泄漏。

循环引用的典型例子

考虑两个类 A 和 B,彼此持有对方的 shared_ptr:

#include 
struct B;

struct A {
    std::shared_ptr ptr;
    ~A() { std::cout << "A destroyed\n"; }
};

struct B {
    std::shared_ptr ptr;
    ~B() { std::cout << "B destroyed\n"; }
};

int main() {
    auto a = std::make_shared();
    auto b = std::make_shared();
    a->ptr = b;
    b->ptr = a;
} // a 和 b 离开作用域,但 A 和 B 的对象不会被析构

在这个例子中,a 和 b 的引用计数都为2:一个来自外部变量,另一个来自对方对象的成员。当 main 函数结束时,外部引用消失,引用计数变为1,但由于互相引用,对象无法被销毁。

weak_ptr 如何打破循环引用

weak_ptr 是一种不增加引用计数的弱引用指针,它指向由 shared_ptr 管理的对象,但不影响其生命周期。它用于观察对象是否还存在,需要时可提升为 shared_ptr。

解决上述问题的方法是:将其中一个方向的 shared_ptr 改为 weak_ptr,从而打破引用环。

立即学习C++免费学习笔记(深入)”;

修改上面的例子:

一览AI绘图
一览AI绘图

一览AI绘图是一览科技推出的AIGC作图工具,用AI灵感助力,轻松创作高品质图片

下载
struct B {
    std::weak_ptr ptr;  // 使用 weak_ptr 替代 shared_ptr
    ~B() { std::cout << "B destroyed\n"; }
};

此时,B 持有的是 A 的弱引用,不增加 A 的引用计数。当 main 函数结束时:

  • a 的引用计数为1(来自 main 中的变量)
  • b 的引用计数为1(来自 main 中的变量)

一旦 a 和 b 离开作用域,引用计数归零,A 和 B 的对象都能被正确析构。

weak_ptr 的常用操作

由于 weak_ptr 不保证所指对象一定存在,使用前需检查:
  • lock():返回一个 shared_ptr,若对象已释放,则返回空 shared_ptr
  • expired():判断所指对象是否已被释放(不推荐直接使用,因有竞态风险)
  • reset():释放 weak_ptr 的引用

示例用法:

std::shared_ptr get_ptr() {
    if (auto p = b.ptr.lock()) {
        return p;  // 对象仍存在
    } else {
        return nullptr;  // 对象已释放
    }
}

总结与建议

在设计涉及双向关联的对象结构时,应避免双方都使用 shared_ptr。通常做法是:
  • 父节点使用 shared_ptr 指向子节点
  • 子节点使用 weak_ptr 指向父节点

这样既能访问父节点,又不会延长其生命周期,有效防止循环引用。

基本上就这些。合理使用 weak_ptr,可以安全地打破 shared_ptr 的循环依赖,让资源得以正确释放。

相关专题

更多
c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

57

2026.01.23

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

57

2026.01.23

yy漫画官方登录入口地址合集
yy漫画官方登录入口地址合集

本专题整合了yy漫画入口相关合集,阅读专题下面的文章了解更多详细内容。

237

2026.01.23

漫蛙最新入口地址汇总2026
漫蛙最新入口地址汇总2026

本专题整合了漫蛙最新入口地址大全,阅读专题下面的文章了解更多详细内容。

393

2026.01.23

C++ 高级模板编程与元编程
C++ 高级模板编程与元编程

本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

17

2026.01.23

php远程文件教程合集
php远程文件教程合集

本专题整合了php远程文件相关教程,阅读专题下面的文章了解更多详细内容。

103

2026.01.22

PHP后端开发相关内容汇总
PHP后端开发相关内容汇总

本专题整合了PHP后端开发相关内容,阅读专题下面的文章了解更多详细内容。

73

2026.01.22

php会话教程合集
php会话教程合集

本专题整合了php会话教程相关合集,阅读专题下面的文章了解更多详细内容。

81

2026.01.22

宝塔PHP8.4相关教程汇总
宝塔PHP8.4相关教程汇总

本专题整合了宝塔PHP8.4相关教程,阅读专题下面的文章了解更多详细内容。

70

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号