shared_ptr
原理是引用计数。每多一个shared指针指向同一个对象时,引用+1,而析构则相反,如果计数为零,则保存的指针被删除。
那shared_ptr 内部是什么样的呢?我们可以看GCC库中shared_ptr的源码。
template<typename _Tp, _Lock_policy _Lp>
class __shared_ptr
: public __shared_ptr_access<_Tp, _Lp>
{
public:
using element_type = typename remove_extent<_Tp>::type; // 移除数组类型的最顶层维度,返回数组元素的类型。
public:
friend class __weak_ptr<_Tp, _Lp>;
private:
// ... 中间省略很多东西
element_type* _M_ptr; // Contained pointer.
<_Lp> _M_refcount; // Reference counter.
__shared_count};
可以看到,shared 指针内部是有2个指针,第一个是指向原始对象的指针,第二个是引用计数的模块。
template<_Lock_policy _Lp = __default_lock_policy>
class _Sp_counted_base
: public _Mutex_base<_Lp>
{
public:
() noexcept
_Sp_counted_base: _M_use_count(1), _M_weak_count(1) { }
private:
(_Sp_counted_base const&) = delete;
_Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
_Sp_counted_base// _Atomic_word 是能够进行原子操作的最小类型,可能是int , long 等。
; // #shared
_Atomic_word _M_use_count; // #weak + (#shared != 0)
_Atomic_word _M_weak_count};
template<_Lock_policy _Lp>
class __shared_count
{
public:
constexpr __shared_count() noexcept : _M_pi(0)
{ }
// 省略一大堆东西
private:
friend class __weak_count<_Lp>;
<_Lp>* _M_pi;
_Sp_counted_base};
template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
{
class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>
{
typedef _Sp_ebo_helper<0, _Deleter> _Del_base;
typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;
public:
(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
_Impl: _Del_base(std::move(__d)), _Alloc_base(__a), _M_ptr(__p)
{ }
& _M_del() noexcept { return _Del_base::_S_get(*this); }
_Deleter& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
_Alloc
;
_Ptr _M_ptr};
// 省略一大堆东西
private:
;
_Impl _M_impl};
基础的_Sp_counted_base
类,有原子类型的 强引用计数和弱引用计数。 其有2个派生类
_Sp_counted_ptr
: 在_Sp_counted_base
, 只有专门保存指向裸对象的指针。 一般在没有配置删除器和分配器函数的时候会被创建使用。- 还有其派生类
_Sp_counted_deleter
, 内部有个数据结构,专门保存指向裸对象的指针、删除器函数指针和分配器函数的指针。