0

0

c++怎么解决循环引用问题_c++ weak_ptr与shared_ptr配合使用【方法】

穿越時空

穿越時空

发布时间:2025-12-27 13:48:08

|

739人浏览过

|

来源于php中文网

原创

shared_ptr循环引用会导致内存泄漏,需用weak_ptr打破引用链;weak_ptr不增加引用计数,访问前须调用lock()获取临时shared_ptr,且应避免滥用以规避设计缺陷。

c++怎么解决循环引用问题_c++ weak_ptr与shared_ptr配合使用【方法】

shared_ptr 循环引用会导致内存泄漏

当两个对象用 shared_ptr 互相持有对方时,引用计数永远无法归零,析构函数不会被调用,内存就一直卡着不释放。这不是“程序崩溃”,而是静默的资源泄露——跑得越久,占用越多。

用 weak_ptr 打破循环中的一个引用链

weak_ptr 不增加引用计数,只“观察”所指向的 shared_ptr 是否还有效。它本身不参与所有权管理,因此不会延长对象生命周期。

典型做法是:一方用 shared_ptr 持有另一方,另一方用 weak_ptr 回指——比如父类持子类的 shared_ptr,子类用 weak_ptr 指向父类。

  • 必须在访问前调用 lock() 转成临时 shared_ptr,否则可能访问已销毁对象
  • weak_ptr 不能直接解引用,也不能参与构造/赋值 shared_ptr
  • 不要长期保存 weak_ptr::lock() 返回的 shared_ptr,除非你真需要延长其生命周期

实际代码中怎么写才安全

下面是一个父子结构的最小可运行示例,展示如何避免循环引用:

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

Looka
Looka

AI辅助Logo和品牌设计工具

下载
#include 
#include 

struct Child;
struct Parent {
    std::shared_ptr child;
    ~Parent() { std::cout << "Parent destroyed\n"; }
};

struct Child {
    std::weak_ptr parent; // 注意:不是 shared_ptr
    ~Child() { std::cout << "Child destroyed\n"; }
};

int main() {
    auto p = std::make_shared();
    auto c = std::make_shared();
    p->child = c;
    c->parent = p; // 只是观察,不增加引用计数

    // 安全访问父对象
    if (auto locked_parent = c->parent.lock()) {
        std::cout << "Parent still alive\n";
    } else {
        std::cout << "Parent already gone\n";
    }
} // 输出:Child destroyed → Parent destroyed(顺序取决于析构时机)

weak_ptr 不是万能的,别滥用

weak_ptr 解决的是“谁该拥有谁”的设计问题,不是补丁工具。如果发现要到处加 weak_ptr,大概率是类职责或生命周期设计不合理。

常见误用包括:

  • weak_ptr 当成“可空指针”替代 shared_ptr 或裸指针——它开销更大,且每次访问都要 lock()
  • 在回调、信号槽等跨线程场景中没考虑 weak_ptr::lock() 的线程安全性(它是线程安全的,但后续使用仍需同步)
  • 忘记检查 lock() 返回是否为空,直接解引用导致未定义行为

真正关键的,是画清楚对象图、标出所有权方向,再决定哪里该用 shared_ptr、哪里该用 weak_ptr,或者干脆换用裸指针 + 明确生命周期约束。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

465

2023.08.10

空指针异常处理
空指针异常处理

本专题整合了空指针异常解决方法,阅读专题下面的文章了解更多详细内容。

19

2025.11.16

ip地址修改教程大全
ip地址修改教程大全

本专题整合了ip地址修改教程大全,阅读下面的文章自行寻找合适的解决教程。

35

2025.12.26

压缩文件加密教程汇总
压缩文件加密教程汇总

本专题整合了压缩文件加密教程,阅读专题下面的文章了解更多详细教程。

18

2025.12.26

wifi无ip分配
wifi无ip分配

本专题整合了wifi无ip分配相关教程,阅读专题下面的文章了解更多详细教程。

46

2025.12.26

漫蛙漫画入口网址
漫蛙漫画入口网址

本专题整合了漫蛙入口网址大全,阅读下面的文章领取更多入口。

94

2025.12.26

b站看视频入口合集
b站看视频入口合集

本专题整合了b站哔哩哔哩相关入口合集,阅读下面的文章查看更多入口。

289

2025.12.26

俄罗斯搜索引擎yandex入口汇总
俄罗斯搜索引擎yandex入口汇总

本专题整合了俄罗斯搜索引擎yandex相关入口合集,阅读下面的文章查看更多入口。

372

2025.12.26

虚拟号码教程汇总
虚拟号码教程汇总

本专题整合了虚拟号码接收验证码相关教程,阅读下面的文章了解更多详细操作。

35

2025.12.25

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

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

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