个人随笔 (Owed by: 春夜喜雨 http:///chunyexiyu)
注:研究代码是在windows上vs2015中的实现
shared_ptr被使用的很广泛,许多经典库使用share_ptr作为实现函数的接口类型使用,确实还是很有必要仔细研究一下;
下面就从代码层来看一看shared_ptr的数据结构情况。
// CLASS TEMPLATE shared_ptr
template<class _Ty>
class shared_ptr : public _Ptr_base<_Ty>
{...}
// CLASS TEMPLATE _Ptr_base
template<class _Ty>
class _Ptr_base
{
...
private:
element_type * _Ptr{nullptr};
_Ref_count_base * _Rep{nullptr};
...
}
_Set_ptr_rep_and_enable_shared(_Px, new _Ref_count<_Ux>(_Px));
_Set_ptr_rep_and_enable_shared(_Px, new _Ref_count_resource<_UxptrOrNullptr, _Dx>(_Px, _STD move(_Dt)));
using _Refd = _Ref_count_resource_alloc<_UxptrOrNullptr, _Dx, _Alloc>;
// CLASS _Ref_count_base
class __declspec(novtable) _Ref_count_base
{
...
_Atomic_counter_t _Uses;
_Atomic_counter_t _Weaks;
_Ref_count_base() : _Uses(1), _Weaks(1) // non-atomic initializations
{// construct}
...
}
template<class _Ty>
class _Ref_count : public _Ref_count_base
{
...
_Ty * _Ptr;
virtual void _Destroy() noexcept override
{ // destroy managed resource
delete _Ptr;
}
...
}
template<class _Resource,class _Dx>
class _Ref_count_resource : public _Ref_count_base
{
...
_Compressed_pair<_Dx, _Resource> _Mypair;
virtual void _Destroy() noexcept override
{ // destroy managed resource
_Mypair._Get_first()(_Mypair._Get_second());
}
...
}
基于上面的代码跟踪分析,可以看出share_ptr构建时:
另外为什么shared_ptr经常会被一些流行库用作接口类型呢?
另外结合make_shared一块来看这个shared_ptr的话,也能看出直接使用make_shared的话,实际采用的是计数和对象绑定的计数类:
// FUNCTION TEMPLATE make_shared
template<class _Ty, class... _Types>
_NODISCARD inline shared_ptr<_Ty> make_shared(_Types&&... _Args)
{// make a shared_ptr
const auto _Rx = new _Ref_count_obj<_Ty>(_STD forward<_Types>(_Args)...);
shared_ptr<_Ty> _Ret;
_Ret._Set_ptr_rep_and_enable_shared(_Rx->_Getptr(), _Rx);
return (_Ret);
}
因为是捆绑申请,内存在一起的,所以就不能分别释放,而是只能在一起释放;从_Ref_count_obj的_Destory函数中就可以看出来,它只调用资源的析构函数,并不去做delete操作的。
template<class _Ty>
class _Ref_count_obj : public _Ref_count_base{
virtual void _Destroy() noexcept override
{ // destroy managed resource
_Getptr()->~_Ty();
}
virtual void _Delete_this() noexcept override
{ // destroy self
delete this;
}
...
}
个人随笔 (Owed by: 春夜喜雨 http:///chunyexiyu)