图文讲解 C++11 智能指针的实现

1、std::shared_ptr

1.1、总体关系

首先我们看看 shared_ptr 相关的类,主要是 __shared_ptr、__shared_count 和 _Sp_counted_base 这三个。

shared_ptr 继承 __shared_ptr,__shared_ptr 有两个成员变量:对象指针 _M_ptr 和引用计数 _M_refcount。

引用计数 __shared_count 主要借助 _Sp_counted_base 实现。

1.2、_Sp_counted_base<Lp>

_Sp_counted_base 是一个基类,有三个派生类,分别用于处理:

  • 传入裸指针
  • 指定 Deleter
  • 使用 make_shared
struct Foo {
  Foo(int val) : val(val) {}
  int val;
};

struct Deleter {
  void operator()(const Foo* p) const { delete p; }
};

std::shared_ptr<Foo> sp1(new Foo(1));
std::shared_ptr<Foo> sp2(new Foo(1), Deleter());
std::shared_ptr<Foo> sp3 = std::make_shared<Foo>(1);

使用 make_shared 方法,共享对象和引用计数在同一块内存。三种情况如下图所示:

<img src='./imgs/sp-counted-base.png'>

_M_dispose() 和 _M_destroy() 两个函数分别释放共享对象和引用计数的内存。由于 make_shared 方法共享对象和引用计数在同一块内存上,_M_despose() 函数只是调用共享对象的析构函数。

  • 当最有一个 shared_ptr 析构时,调用 _M_dispose() 函数释放共享对象内存
  • 当最后一个 weak_ptr 析构时,调用 _M_destroy() 函数释放引用计数内存

从上图可以看到,weak count = #weak + (#shared != 0),这么做的目的,是为了保证 shared_ptr 对象释放了,weak_ptr 对象还可以继续使用。

2、std::weak_ptr

不控制所指向对象生命周期的智能指针,它指向一个 shared_ptr 管理的对象,和 shared_ptr 共享引用计数对象。

weak_ptr 操作 _M_weak_count 计数,在最后一个 weak_ptr 析构时,释放引用计数内存。

3、enable_shared_from_this

enable_shared_from_this 字如其名,“只从 this 指针构造一个 shared_ptr 对象”。当然,并不是直接用 this 指针,而是在一个类的(成员函数)内部,构造该类的 shared_ptr 对象,并且和已有 shared_ptr 共享状态。

enable_shared_from_this 拥有一个 weak_ptr 成员 _M_weak_this,shared_from_this() 函数就是通过这个 weak_ptr 提升为 shared_ptr 返回给 user

比较有意思的是 _M_weak_this 的赋值,并不是在 enable_shared_from_this 构造函数中完成赋值的,而是在 __shared_ptr 构造函数中,调用 _M_enable_shared_from_this() 函数完成的。

_M_enable_shared_from_this() 函数使用模板,如果某个类是 enable_shared_from_this 的子类,就调用 _M_weak_assign() 函数。_M_weak_assign() 函数直接调用 weak_ptr::_M_assign() 函数完成对 weak_ptr 的赋值。

点击关注 “源知源为”,阅读更多技术干货
#智能指针##C++##C++11##应届生##shared_ptr#
C/C++基础 文章被收录于专栏

C/C++ 语言基础

全部评论
m
1 回复 分享
发布于 2023-08-07 09:48 重庆
好文,图很清晰
点赞 回复 分享
发布于 2023-08-05 09:39 江苏

相关推荐

头像
10-15 22:27
已编辑
门头沟学院 C++
罗格镇的小镇做题家:我投了hr打电话来说学历太低了不符合要求,建议投荣耀,结果荣耀也投了一定水花没有,非本211硕
投递华为等公司10个岗位
点赞 评论 收藏
分享
Yushuu:你的确很厉害,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了😆
点赞 评论 收藏
分享
2 21 评论
分享
牛客网
牛客企业服务