图文讲解 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++ 语言基础