shared_ptr源码结构分析

shared_ptr是智能指针的一种,相较于unique_ptr,引入了引用计数的概念,可以支持多个智能指针指向同一资源,由引用计数的增减来描述资源的共享或内存释放,引用计数降为0的时候,资源所占用的内存空间会被释放。

观察其源码结构,可以发现shared_ptr是一个模板派生类,_Ptr_base为它的基类。

Shared_ptr模板类分析


shared_ptr模板类没有自己的数据成员,而是只提供了一些供调用的接口,其中包括:构造函数(有多个不同版本的构造函数,对应不同的函数参数),值得注意的是,其中有一个construct from unique_ptr,由unique_ptr作为函数参数来构造shared_ptr,并且,该参数是个右值引用

这也不难理解,因为unique_ptr无法拷贝,保证资源的唯一性,可以通过move()函数来传参,即下面的代码,构造出p之后,p1也就失效了。

接下来是运算符重载部分,shared_ptr提供了很多运算符的重载,使其使用起来接近于普通的指针,包括了“=”、“*”、“->”、“()”、“.”这些,其中每个重载函数都有许多版本,对应不同的需求,以“=”运算符重载为例,就提供了5个不同的版本。


而对于其他运算符,则是模仿指针的使用,比如“*”运算符返回指针指向的内容,“->”运算符则返回原指针。get()接口是_Ptr_Base类的,具体就是返回原指针。


最后是一些接口,包括swap、reset等等,从字面意思即可理解其作用。注意到reset的实现是通过swap函数的,这其实类似容器的内存清空,比如清空vector,也就是将其capacity置0,就可以这么写,vector().swap(原容器)。

以上就是shared_ptr模板类的大体结构,可以看到这个类只是提供了一些接口,具体的数据成员(原指针以及引用计数相关的数据成员),其实都是_Ptr_base类里,下面就看看这个类具体包含了什么。

_Ptr_base基类分析,该类是weak_ptr和shared_ptr的共同基类


我们主要关注其数据成员,可以看到有两个数据成员:分别是_Ptr和_Rep,类型分别是element_type和_Ref_count_base,根据其命名就可以得知:_Ptr就是原始指针,而_Rep则是控制引用计数的指针,


那么_Ref_count_base类又是什么呢,继续看一下:

看到 _Ref_count_base类是一个抽象类,它有两个重要的数据成员和一些纯虚函数(在_Ref_count类中进行实现):

_Atomic_counter_t类型其实就是unsigned long类型,如下:

接下来,_Ref_count_base有一个派生类_Ref_count,这是真正的引用计数器对象,有一个数据成员_Ptr,就是原始指针。在 _Ref_count类里,对 _Ref_count_base抽象基类的纯虚函数进行了实现

使用的时候,即会将子类指针强转为基类指针。

计数器增减分析


shared_ptr直接用原始指针构造时,先从基类开始:
会初始化基类数据成员_Ty* _Ptr,然后创建_Ref_count_base对象,_Ref_count_base对象创建时,会分别为_Uses和_Weaks赋值为1,其中_Uses即为shared_ptr的引用计数。
具体计数器增减情况如下:
1、涉及到shared_ptr的拷贝,其所指对象的引用计数会递增,比如以下情况:
用一个shared_ptr初始化另一个shared_ptr
用一个shared_ptr给另一个shared_ptr赋值
将shared_ptr作为参数传递给一个函数
shared_ptr作为函数的返回值

2、引用计数减少的情况
给shared_ptr赋予一个新值
shared_ptr为局部变量离开作用域失效,或者shared_ptr被销毁。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值