码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • C++11的weak_ptr弱引用的智能指针


            弱引用指针weak_ptr是用来监视shared_ptr的,不会使引用计数器加1,它不管理shared_ptr内部的指针,主要是为了监视shared_ptr的生命周期,更像是shared_ptr的一个助手。weak_ptr没有重载操作符*和->,因为它不共享指针,不能操作资源,主要是为了通过shared_ptr获得资源的监测权,它的构造函数不会增加引用计数,它的析构不会减少引用计数,纯粹只是作为一个旁观者来监视shared_ptr中管理的资源是否存在。weak_ptr还可以用来返回this指针和解决循环引用的问题。

    weak_ptr基本用法

            1、通过use_count()方法来获得当前观测资源的引用计数,代码如下:

    1. #include
    2. #include
    3. using namespace std;
    4. int main()
    5. {
    6. shared_ptr<int> sp(new int(1));
    7. weak_ptr<int> wp(sp);
    8. ///输出1
    9. cout << sp.use_count() << endl;
    10. ///输出1
    11. cout << wp.use_count() << endl;
    12. shared_ptr<int> sp2(new int(2));
    13. sp2 = sp;
    14. ///输出2
    15. cout << sp.use_count() << endl;
    16. return 0;
    17. }

            2、通过expired()方法来判断所检测的资源是否已经被释放,代码如下:

    1. #include
    2. #include
    3. using namespace std;
    4. int main()
    5. {
    6. shared_ptr<int> sp(new int(1));
    7. weak_ptr<int> wp(sp);
    8. if (wp.expired())
    9. {
    10. cout << "weak_ptr无效,所监视的智能指针被释放" << endl;
    11. }
    12. else
    13. {
    14. cout << "weak_ptr 有效" << endl;
    15. }
    16. return 0;
    17. }

            3、通过lock方法来获取所监视的shared_ptr,代码如下:

    1. #include
    2. #include
    3. using namespace std;
    4. std::weak_ptr<int> gw;
    5. void f()
    6. {
    7. if (gw.expired()) ///所监听的shared_ptr是否被释放
    8. {
    9. cout << "gw is exipired" << endl;
    10. }
    11. else
    12. {
    13. auto spt = gw.lock();
    14. cout << *spt << endl;
    15. }
    16. }
    17. int main()
    18. {
    19. {
    20. shared_ptr<int> sp(new int(1));
    21. gw = sp;
    22. f();
    23. }
    24. f();
    25. return 0;
    26. }

             输出如下:

    1. 1
    2. gw is expired

    weak_ptr返回this指针

            不能直接将this指针返回为shared_ptr,需要通过派生std::enable_shared_from_this类,并通过其方法shared_from_this来返回智能指针,原因是std::enable_shared_from_this类中有一个weak_ptr,这个weak_ptr用来观测this指针,调用shared_from_this()方法时,会调用内部这个weak_ptr的lock()方法,将所观测的shared_ptr返回,看下面代码:

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. struct A : public std::enable_shared_from_this
    7. {
    8. shared_ptr GetSelf()
    9. {
    10. return shared_from_this();
    11. }
    12. ///析构函数调用了1次
    13. ~A()
    14. {
    15. cout << "delete A" << endl;
    16. }
    17. };
    18. int main()
    19. {
    20. shared_ptr sp1(new A);
    21. shared_ptr sp2 = sp1->GetSelf();
    22. return 0;
    23. }

            输出结果如下:

    deleted A

            在外面创建A对象的智能指针和通过该对象返回this的智能指针都是安全的,因此shared_from_this是内部的weak_ptr调用lock()方法之后返回的智能指针,在离开作用域之后,sp1的引用计数减为0,A对象会被析构,不会出现A对象被析构两次的问题。

    weak_ptr解决循环引用问题

            智能指针的循环引用会导致内存泄漏问题,请看下面的代码:

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. struct A;
    7. struct B;
    8. struct A
    9. {
    10. std::shared_ptr bptr;
    11. ~A()
    12. {
    13. cout << "A is deleted" << endl;
    14. }
    15. };
    16. struct B
    17. {
    18. std::shared_ptr aptr;
    19. ~B()
    20. {
    21. cout << "B is deleted" << endl;
    22. }
    23. };
    24. int main()
    25. {
    26. {
    27. ///析构函数没有被调用
    28. shared_ptr ap(new A);
    29. shared_ptr bp(new B);
    30. ap->bptr = bp;
    31. bp->aptr = ap;
    32. ///引用计数为2
    33. cout << "ap use_count: " << ap.use_count() << endl;
    34. cout << "bp use_count: " << bp.use_count() << endl;
    35. }
    36. return 0;
    37. }

            在这个例子中,由于循环引用导致ap和bp的引用计数都为2,离开作用域之后引用计数减为1,不会去删除指针,导致内存泄漏。通过weak_ptr就可以解决这个问题,只要将A或者B的任意一个成员变量改为weak_ptr即可。

    1. struct A;
    2. struct B;
    3. struct A
    4. {
    5. std::shared_ptr bptr;
    6. ~A()
    7. {
    8. cout << "A is deleted" << endl;
    9. }
    10. };
    11. struct B
    12. {
    13. std::weak_ptr aptr;
    14. ~B()
    15. {
    16. cout << "B is deleted" << endl;
    17. }
    18. };
    19. int main()
    20. {
    21. {
    22. shared_ptr ap(new A);
    23. shared_ptr bp(new B);
    24. ap->bptr = bp;
    25. bp->aptr = ap;
    26. ///引用计数为1
    27. cout << "ap use_count: " << ap.use_count() << endl;
    28. cout << "bp use_count: " << bp.use_count() << endl;
    29. }
    30. return 0;
    31. }

            输出如下:

    1. ap use_count: 1
    2. bp use_count: 2
    3. A is deleted
    4. B is deleted

            这样在对B的成员赋值时,即执行bp->aptr = ap;时,由于aptr是weak_ptr,它并不会增加引用计数,所以ap的引用计数仍然会是1,在离开作用域之后,ap的引用计数会减少为0,A指针会被析构,析构后其内部的ptr的引用计数为减为1,然后再离开作用域后bp引用计数又从1减到0,B对象也会被析构,不会发生内存泄漏。

  • 相关阅读:
    怎么成为稚晖君?
    ‍ IT行业就业趋势:哪些方向更受青睐?
    计算S=a+aa+…+aa…a
    python安装
    WebSocket通信安全概览
    Java项目:电器商城系统(java+SSM+JSP+jQuery+javascript+Mysql)
    leetcode:LCP 42. 玩具套圈【数据范围优化模拟集合题】
    黑马JVM总结(十二)
    jwt的了解和使用以及大致代码分析
    Nginx+Tomcat负载均衡、动静分离群集
  • 原文地址:https://blog.csdn.net/qq_25048473/article/details/134545303
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号