share_ptr
首先来看shared_ptr,先贴一小部分vs2013里的实现
// TEMPLATE CLASS shared_ptr
template<class _Ty>
class shared_ptr
: public _Ptr_base<_Ty>
{ // class for reference counted resource management
public:
typedef shared_ptr<_Ty> _Myt;
typedef _Ptr_base<_Ty> _Mybase;
shared_ptr() _NOEXCEPT
{ // construct empty shared_ptr
}
template<class _Ux>
explicit shared_ptr(_Ux *_Px)
{ // construct shared_ptr object that owns _Px
_Resetp(_Px);
}
template<class _Ux,
class _Dx>
shared_ptr(_Ux *_Px, _Dx _Dt)
{ // construct with _Px, deleter
_Resetp(_Px, _Dt);
}
shared_ptr(nullptr_t)
{ // construct empty shared_ptr
}
......
}
我们可以看到shared_ptr首先继承了_Ptr_base。把_Ptr_base部分代码贴上来
// TEMPLATE CLASS _Ptr_base
template<class _Ty>
class _Ptr_base
{ // base class for shared_ptr and weak_ptr
public:
typedef _Ptr_base<_Ty> _Myt;
typedef _Ty element_type;
_Ptr_base()
: _Ptr(0), _Rep(0)
{ // construct
}
_Ptr_base(_Myt&& _Right)
: _Ptr(0), _Rep(0)
{ // construct _Ptr_base object that takes resource from _Right
_Assign_rv(_STD forward<_Myt>(_Right));
}
template<class _Ty2>
_Ptr_base(_Ptr_base<_Ty2>&& _Right)
: _Ptr(_Right._Ptr), _Rep(_Right._Rep)
{ // construct _Ptr_base object that takes resource from _Right
_Right._Ptr = 0;
_Right._Rep = 0;
}
_Myt& operator=(_Myt&& _Right)
{ // construct _Ptr_base object that takes resource from _Right
_Assign_rv(_STD forward<_Myt>(_Right));
return (*this);
}
private:
_Ty *_Ptr;
_Ref_count_base *_Rep;
template<class _Ty0>
friend class _Ptr_base;
}
可以发现_Ptr就是用来保存原始指针的变量,_Rep是_Ref_count_base类型的指针,根据变量名大概就是引用计数了。再把_Ref_count_base的代码贴上来
// CLASS _Ref_count_base
class _Ref_count_base
{ // common code for reference counting
private:
virtual void _Destroy() = 0;
virtual void _Delete_this() = 0;
private:
_Atomic_counter_t _Uses;
_Atomic_counter_t _Weaks;
protected:
_Ref_count_base()
{ // construct
_Init_atomic_counter(_Uses, 1);
_Init_atomic_counter(_Weaks, 1);
}
public:
virtual ~_Ref_count_base() _NOEXCEPT
{ // ensure that derived classes can be destroyed properly
}
bool _Incref_nz()
{ // increment use count if not zero, return true if successful
for (; ; )
{ // loop until state is known
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_CEE_PURE)
_Atomic_integral_t _Count =
static_cast<volatile _Atomic_counter_t&>(_Uses);
if (_Count == 0)
return (false);
if (static_cast<_Atomic_integral_t>(_InterlockedCompareExchange(
reinterpret_cast<volatile long *>(&_Uses),
_Count + 1, _Count)) == _Count)
return (true);
#else /* defined(_M_IX86) || defined(_M_X64) || defined(_M_CEE_PURE) */
_Atomic_integral_t _Count =
_Load_atomic_counter(_Uses);
if (_Count == 0)
return (false);
if (_Compare_increment_atomic_counter(_Uses, _Count))
return (true);
#endif /* defined(_M_IX86) || defined(_M_X64) || defined(_M_CEE_PURE) */
}
}
unsigned int _Get_uses() const
{ // return use count
return (_Get_atomic_count(_Uses));
}
void _Incref()
{ // increment use count
_MT_INCR(_Mtx, _Uses);
}
void _Incwref()
{ // increment weak reference count
_MT_INCR(_Mtx, _Weaks);
}
void _Decref()
{ // decrement use count
if (_MT_DECR(_Mtx, _Uses) == 0)
{ // destroy managed resource, decrement weak reference count
_Destroy();
_Decwref();
}
}
void _Decwref()
{ // decrement weak reference count
if (_MT_DECR(_Mtx, _Weaks) == 0)
_Delete_this();
}
long _Use_count() const
{ // return use count
return (_Get_uses());
}
bool _Expired() const
{ // return true if _Uses == 0
return (_Get_uses() == 0);
}
virtual void *_Get_deleter(const _XSTD2 type_info&) const
{ // return address of deleter object
return (0);
}
};
比较短就全贴上来了,可以看到_Uses和_Weaks都被初始化成1。当我们平时使用 std::shared_ptr a(new int(1)) 这种形式,shared_ptr会使用_Resetp()来初始化。把_Resetp()代码贴上来
template<class _Ux>
void _Resetp(_Ux *_Px)
{ // release, take ownership of _Px
_TRY_BEGIN // allocate control block and reset
_Resetp0(_Px, new _Ref_count<_Ux>(_Px));
_CATCH_ALL // allocation failed, delete resource
delete _Px;
_RERAISE;
_CATCH_END
}
...
public:
template<class _Ux>
void _Resetp0(_Ux *_Px, _Ref_count_base *_Rx)
{ // release resource and take ownership of _Px
this->_Reset0(_Px, _Rx);
_Enable_shared(_Px, _Rx);
}
....
// TEMPLATE CLASS _Ref_count
template<class _Ty>
class _Ref_count
: public _Ref_count_base
{ // handle reference counting for object without deleter
public:
_Ref_count(_Ty *_Px)
: _Ref_count_base(), _Ptr(_Px)
{ // construct
}
private:
virtual void _Destroy()
{ // destroy managed resource
delete _Ptr;
}
virtual void _Delete_this()
{ // destroy self
delete this;
}
_Ty * _Ptr;
};
....
void _Reset0(_Ty *_Other_ptr, _Ref_count_base *_Other_rep)
{ // release resource and take new resource
if (_Rep != 0)
_Rep->_Decref();
_Rep = _Other_rep;
_Ptr = _Other_ptr;
}
可以看到最终在_Reset0中原始指针和在堆中的引用计数的指针都被保存下来,一个有趣的发现在引用计数中还保存着一份原始指针,有时间再慢慢探索。