c++中shared_ptr的循环引用问题如何解决

目录

1.什么是循环引用

2.如何解决循环引用

3.weak_ptr 怎么解决循环引用的呢?

1.当shared_ptr的引用计数--时

2.当weak_ptr的引用计数--时

1.什么是循环引用

我们知道当 shared_ptr 的引用计数为零时,shared_ptr所指向的对象就会被释放

那么两个shared_ptr互相指向对方会发生什么呢?

循环引用简单例子

class B;

class A
{
public:
    std::shared_ptr<B> ptr_to_b;

    ~A()
    {
        std::cout << "A is being destroyed" << std::endl;
    }
};

class B
{
public:
    std::shared_ptr<A> ptr_to_a;

    ~B()
    {
        std::cout << "B is being destroyed" << std::endl;
    }
};

int main()
{
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();
    
    cout << a.use_count() << endl;
    cout << b.use_count() << endl;

    // 创建循环引用
    a->ptr_to_b = b;
    b->ptr_to_a = a;

    cout << a.use_count() << endl;
    cout << b.use_count() << endl;

    return 0;
}

结果呢,shared_ptr 对象一直没被释放,因为引用计数一直不为零

没有 原对象没有调用析构函数

2.如何解决循环引用

我们只要把两个shared_ptr的其中一个换成weak_ptr就可以了

class B;

class A
{
public:
    std::shared_ptr<B> ptr_to_b;

    ~A()
    {
        std::cout << "A is being destroyed" << std::endl;
    }
};

class B
{
public:
    std::weak_ptr<A> ptr_to_a;

    ~B()
    {
        std::cout << "B is being destroyed" << std::endl;
    }
};

int main()
{
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();

    cout << a.use_count() << endl;
    cout << b.use_count() << endl;

    // 创建循环引用
    a->ptr_to_b = b;
    b->ptr_to_a = a;

    cout << a.use_count() << endl;
    cout << b.use_count() << endl;

    return 0;
}

把一方换成 weak_prt 后 ,成功调用析构函数

3.weak_ptr 怎么解决循环引用的呢?

在STL的shared_ptr源码中我们可以发现一共有两个引用计数

一个是负责管理shared_ptr的指向的对象

(表示有多少个 shared_ptr 指向同一个对象)

一个是负责管理weak_ptr的

(表示有多少个 weak_ptr 指向同一个对象)

当我们使用weak_ptr去指向shared_ptr的时,我们并不会增加 shared_ptr 的引用计数,

而是增加weak_ptr的引用计数

1.当shared_ptr的引用计数--时

    _Sp_counted_base<_S_single>::_M_release() noexcept
    {
      if (--_M_use_count == 0)
        {
          _M_dispose();//删除shared_ptr指向的原对象
          if (--_M_weak_count == 0)
            _M_destroy();//删除weak_ptr这个类
        }
    }

2.当weak_ptr的引用计数--时

    _Sp_counted_base<_S_single>::_M_weak_release() noexcept
    {
      if (--_M_weak_count == 0)
        _M_destroy();//weak_ptr这个类删除,并不删除原对象
    }

我们可以发现 weak_ptr的引用计数为零时,并不删除shared_ptr指向的对象,

也就是说weak_ptr不参与操作目标

注意:当share计数为0时, 原对象直接被删除没有了,使用weak_ptr直接失效

      bool
      expired() const noexcept
      { return _M_refcount._M_get_use_count() == 0; }

这个源码就是 查看weak_ptr 是否失效,失效我们就delete

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
shared_ptr循环引用是指多个shared_ptr实例互相引用,导致对象无法被释放的情况。shared_ptr采用引用计数的智能指针,可以指向同一个动态对象,并维护了一个共享引用计数器。当多个shared_ptr实例相互引用时,它们的引用计数无法降为零,从而导致内存泄漏。 为了解决shared_ptr引起的循环引用问题,可以使用weak_ptr指针。weak_ptr是一种弱引用,不能单独使用,只能配合shared_ptr使用。相比之下,weak_ptr并不增加引用计数,它只是提供了对被共享对象的一个非拥有的引用。通过使用weak_ptr,可以打破shared_ptr之间的循环引用,使对象能够正常释放。 在C++,我们可以使用weak_ptr的lock()函数来获取一个可用的shared_ptr对象,从而访问被共享对象的成员函数和成员变量。weak_ptr没有重载*和->运算符,因此无法直接访问对象,但可以使用lock()函数来获取shared_ptr,并通过该shared_ptr来访问对象的成员。 通过使用weak_ptr解决shared_ptr循环引用问题,可以避免内存泄漏和资源占用过多的情况。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++11智能指针之weak_ptr详解](https://download.csdn.net/download/weixin_38740201/14841441)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [C++ 智能指针循环引用问题](https://blog.csdn.net/qq_28584889/article/details/88726324)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [C++智能指针(share_ptr)及其循环引用问题](https://blog.csdn.net/feikudai8460/article/details/104747490)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值