shellmad-25_C++新特性 强弱指针计数器增减分析

本文详细解析了智能指针的计数器管理机制,包括强弱指针在构造、赋值和提升时计数器的变化过程。通过实例代码追踪,展示了如何理解引用计数的增减规则,重点讲解了`std::shared_ptr`和`std::weak_ptr`的行为。
摘要由CSDN通过智能技术生成

这节课讲讲
智能指针的计数器如何去管理的

以及我们自己来编写一个自己的有强弱指针关系的智能指针版本

具体而言:

按道理, 我们要跟踪源码, 为什么呢
因为我们要知道几个问题
何时我们的强指针次数会+1, 何时我们的弱指针次数会+1
我们需要去跟踪

这里我们提供跟踪的思路

强指针构造, 析构, =赋值, 拷贝构造等情况下, 计数器的变化
弱指针构造, 析构, =赋值, 拷贝构造等情况下, 计数器的变化
弱指针提升为强指针, 计数器变化


代码运行分析:

强指针构造的时候, 计数器变化情况

单步走, f5,

    std::shared_ptr<int> sptr(new int(3));

进入shared_ptr的构造函数
在这里插入图片描述
用的是以下类型的构造
在这里插入图片描述
但是这样来有一个问题, 构造的时候需要先到父类Ptr_base, 再到子类, 让我们看下是不是这样的

单步走, 进到父类Ptr_base
在这里插入图片描述

到父类后, 先进行初始化操作, 将父类的内部指针_Ptr置为空和引用次数_Rep置为空

从父类Ptr_base出来之后, 到真正的构造函数里
在这里插入图片描述
Restp(_Px)里, 按道理, 应该赋予内部指针_Ux _Px, 然后引用次数变一变

单步走,f11进来(视频发现f11进不去, 直接手动进去看)

有点复杂, 有个delete _Px 删除原始的, try catch异常处理结构
核心代码只要看_Resetp0(_Px, new _Ref_count<_UX>(_Px));
在这里插入图片描述
然后到_Resetp0里看, 进行了一些初始化操作, _Ref_count_base* _Rx是外面new出来, 然后传进来的
在这里插入图片描述
在这里插入图片描述

然后再进来看 _Ref_count的构造里的次数, 那么构造里的次数应该怎么做呢

发现_Ref_count的构造 用的是_Ref_count_base()的构造函数
在这里插入图片描述
然后回到_Ref_count_base的构造函数, 按道理, 父类的构造函数没什么好看的

发现父类_Ref_count_base(), 直接将两个引用计数初始化为1
为了让我们支持多线程操作, 这个操作是一个原子操作
在这里插入图片描述

总结:
首先要初始化父类的指针, 会把内部_Ux*_Px指针传进来
Resetup0, 对第1个参数内部指针的操作只是简单的赋值
第2个参数new _Ref_count<_Ux>(_Px));, 是要把内部的计数器更新下

_Ref_count类没进行什么操作, 关键在它的父类 _Ref_count_base

父类_Ref_count_base里, 分别对 _Uses_Weaks赋值为1

强指针直接构造(拿原始指针构造)时,
1.初始化_Ty* _Ptr
2.创建_Ref_count对象
3. _Ref_count_base对象构造时, 会分别会为_Uses = 1(因为对象有人在使用, 所以赋值为1), 并且_Weaks = 1(_Weaks = 1是为了统计方案, 赋值为1, 也表达出有一个人在使用对象)
然后Weaks 1 - 1 = 0(-1后的值, 才表示外界有多少弱指针在使用)

计数器加减规则
在这里插入图片描述
2.另外一个对象通过拷贝构造, =赋值给新的shared_ptr, 那么内部指针计数器+1

因为内部对象有新的人在使用它, 自身计数器不变是因为没有弱指针

share给weak, 内部指针不变, 因为外界的shared_ptr表示的内部计数器没有变化, 而weak多了一个, 自身引用计数器+1, 表示外界有新的人在使用

从weak中获取一个shared_ptr, 内部计数器+1, 自身不变

减少也是类似, 当shared_ptr析构的时候, 内部计数器-1, 当内部计数器减少为0的时候, 则释放内部对象, 同时会将自身计数器(弱指针计数器)-1
如果引用计数器减为了0, 就将引用计数器(Ref)释放掉

同理Weak在析构的时候, 只减自身的计数器, 自身计数器减为0, 就释放_Ref_count对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值