• 智能指针简述 解决循环引用的weak_ptr


    1.智能指针通过RAII方法来管理指针:构造对象时,完成资源初始化;析构对象时,对资源进行清理及汕尾.

      2.auto_ptr,通过“转移所有权”来防止析构一块内存多次.(如何转移?详情看第二篇文章)

      3.scoped_ptr,不“转移所有权”而是禁止拷贝/赋值对象.(C++如何禁止拷贝对象?详情看第三篇文章)

      4.shared_ptr,通过"引用计数"的方法,来完成对象的拷贝/赋值.(引用计数怎么实现?详情看上篇文章)

      大致总结了一下前文后,我们开始讨论今天的内容:解决智能指针的循环引用问题!

      我们先来看一下这样的场景:

    template<typename T>
    struct ListNode{
        T _value;
        std::shared_ptr<ListNode> _prev;
        std::shared_ptr<ListNode> _next;
     
        ListNode(const T & value)
            :_value(value)
            ,_prev(NULL)
            ,_next(NULL){}
     
        ~ListNode(){
            std::cout<<"~ListNode()"<<std::endl;
        }
    };
     
    void TestWeekPtr(){
        std::shared_ptr<ListNode<int>> sp1(new ListNode<int>(10));
        std::shared_ptr<ListNode<int>> sp2(new ListNode<int>(20));
        sp1->_next = sp2;
        sp2->_prev = sp1;
        //构成死锁,出了函数作用域,也没有调用析构函数
        std::cout<<sp1.use_count()<<std::endl;  //sp1的引用计数
        std::cout<<sp2.use_count()<<std::endl;  //sp2的引用计数
    }
     

      sp1指向sp2、sp2又指向sp1,这种情况,就好像两个人打架:互相抓住对方耳朵,A说你先松手,你不松我就不松;B说你先松,你不松我也不松.就这样一直僵持着.....

      那么,我们如何解决这样的问题呢?

      用weak_ptr!!!

     
    template<typename T>
    struct ListNode{
        T _value;
        weak_ptr<ListNode> _prev;
        weak_ptr<ListNode> _next;
         
        ListNode(const T & value)
            :_value(value)
            ,_prev(NULL)
            ,_next(NULL){}
     
        ~ListNode(){
            std::cout<<"~ListNode()"<<std::endl;
        }
    };
    void TestWeekPtr(){
        std::shared_ptr<ListNode<int>> sp1(new ListNode<int>(10));
        std::shared_ptr<ListNode<int>> sp2(new ListNode<int>(20));
        sp1->_next = sp2;
        sp2->_prev = sp1;
     
        std::cout<<sp1.use_count()<<std::endl;
        std::cout<<sp2.use_count()<<std::endl;
    }

     输出:

    1
    1
    ~ListNode()
    ~ListNode()
     

      那么为什么用weak_ptr就可以解决循环引用的问题,简单点的来说:weak_ptr的构造和析构不会引起引用计数的增加或减少.

      最后,作为补充:weak_ptr必须与shared_ptr配合使用,不能单独使用.

  • 相关阅读:
    Virtio:针对 Linux 的 I/O 虚拟化框架
    修复MySQL的MyISAM表命令check table用法
    Linux 下用 smartd 监测硬盘状况
    借助JVM生日的时机,说说关于JVM你所不知道的那些事
    实时流计算、Spark Streaming、Kafka、Redis、Exactly-once、实时去重
    使用Kafka、Elasticsearch、Grafana搭建业务监控系统(三)Elasticsearch
    zabbix监控多实例tomcat--不使用JMX
    KAFKA随机产生JMX 端口指定的问题
    nginx+keepalived高可用服务器宕机解决方案
    tomcat 内存参数优化示例
  • 原文地址:https://www.cnblogs.com/sharecenter/p/14710208.html
Copyright © 2020-2023  润新知