可以通过模板参数指定Lock_Policy
class sp_counted_Base{}
- use_count => 当减为0析构资源 dispose
weak_count => 当减为0
delete this;
destroy释放控制区域二者皆为原子变量,原子操作改变值,同时使用内存屏障确保可见性 dispose一定要能被调用destroy的线程观察到
class sp_counted_Ptr{}
继承了sp_counted_Base
class sp_counted_deleter{}
继承了sp_counted_Base
,存储了Deleter_
,使用std::addressof 1获取地址非常有趣,当面对模板时,传入的类型的& operator可能被重载,并非取地址的含义,因此使用这个弥补。
class _shared_count
进一步封装,作为控制块class _shared_ptr
继承了class shared_ptr_access
,后者重载了* 和 -> 运算符class _weak_ptr
使用class _weak_count
作为控制块,增加引用计数有区别class enable_shared_from_this
使用weak_ptr weak_this
来实现自身返回shared_ptr实现原理并没有什么黑魔法:当从指针构造shared_ptr时,在weak_this中进行记录(将this指针赋值给weak_this),当使用shared_from_this的时候,将weak_this提升为shared_ptr返回
- Atomic 的实现采用了 int + atomic_fetch_and_add + atomic_thread_fence(memory barrier)因为是非原子操作,所以才需要内存屏障
注释1:
- 如果开启EBO(类型满足不为final且为空),则Sp_ebo_helper继承了
_Tp
, 直接将该对象转为_Tp类型对象 - 如果不开启,有一个成员变量存储_Tp对象
- 而_Impl又继承了 Sp_ebp_helper, 相当于直接继承了这个对象?
- __Sp_counted_ptr 是默认删除器,使用delete删除
- 当传入自定义删除器时,构造一个Sp_counted_deleter
在探究为什么
get_deleter
函数需要rtti信息时,有了意外收获,虚函数的正确调用不需要rtti2为什么? 因为需要主动校对type_info信息
- 在shared_ptr构造的时候,需要检验是否有weak_this.这一处是模板精髓(检测对象是否拥有某个成员函数)
扩展:dynamic_cast原理和rtti
开启 fno-rtti 后,不可以使用dynamic_cast 和 typeid,但是节省空间
dynamic_cast 和 typeid 都使用了额外的空间来存储必要的类型信息(type_info),运行时查找这些信息去判断。而虚函数的调用不需要这些信息。
扩展:为什么unique_ptr大小和指针相同
使用了(employ) EBO (empty base optimization),作为基类初始化不需要占用额外空间,详见3
当使用了empty deleter object (重载了()的类)且unique_ptr使用了EBO后
扩展:其他笔记4
- why use std::addressof versus &: https://stackoverflow.com/que... ↩
- shared_ptr withou rtti: https://stackoverflow.com/que... ↩
- overhead of custom deleter: https://www.bourez.be/?p=19 ↩
- 一位博主的智能指针源码阅读 https://blog.csdn.net/kupepoe... ↩
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。