shared_ptr & weak_ptr
本次源码采用的是vs2015 c++11的源码进行分析
sizeof(shard_ptr)=?
回答这个问题,就需要看shared_ptr 的数据结构,下边进行源码分析
shared_ptr
C++ template class shared_ptr : public _Ptr_base<_Ty> |
_Ptr_base<_Ty>
C++ template class _Ptr_base { // base class for shared_ptr and weak_ptr public: typedef _Ptr_base<_Ty> _Myt; typedef _Ty element_type; private: _Ty *_Ptr; _Ref_count_base *_Rep; } |
也就是说 shared_ptr 内部数据就是两个指针_Ptr 与 _Rep
那就很好理解了,在32位字节上4字节对齐情况下是8个字节
在64位机器上,8字节对齐请下是16个字节
shared_ptr 引用计数为0的时候做了什么
shared_ptr::_Reset0
C++ template class shared_ptr : public _Ptr_base<_Ty> { void _Reset() { // release resource _Reset(0, 0); }
template void _Reset(const _Ptr_base<_Ty2>& _Other) { // release resource and take ownership of _Other._Ptr _Reset(_Other._Ptr, _Other._Rep); }
template void _Reset(const _Ptr_base<_Ty2>& _Other, bool _Throw) { // release resource and take ownership from weak_ptr _Other._Ptr _Reset(_Other._Ptr, _Other._Rep, _Throw); } template void _Reset(auto_ptr<_Ty2>&& _Other) { // release resource and take _Other.get() _Ty2 *_Px = _Other.get(); _Reset0(_Px, new _Ref_count<_Ty>(_Px)); _Other.release(); _Enable_shared(_Px, _Rep); } 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; } } |
_Ref_count_base::_Decref
C++ class _Ref_count_base { // common code for reference counting _Atomic_counter_t _Uses; _Atomic_counter_t _Weaks; void _Decref() { // decrement use count if (_MT_DECR(_Uses) == 0) { // destroy managed resource, decrement weak reference count _Destroy(); _Decwref(); } } virtual void _Delete_this() = 0; virtual void _Destroy() _NOEXCEPT { // destroy managed resource delete _Ptr; } void _Decwref() { // decrement weak reference count if (_MT_DECR(_Weaks) == 0) _Delete_this(); } }; |
_Ref_count_del::_Delete_this
C++ template class _Dx> class _Ref_count_del : public _Ref_count_base { // handle reference counting for object with deleter public: _Ref_count_del(_Ty *_Px, _Dx _Dt) : _Ref_count_base(), _Mypair(_One_then_variadic_args_t(), _Dt, _Px) { // construct }
virtual void *_Get_deleter( const _XSTD2 type_info& _Typeid) const _NOEXCEPT { // return address of deleter object return ((void *)(_Typeid == typeid(_Dx) ? _STD addressof(_Mypair._Get_first()) : 0)); }
private: virtual void _Destroy() _NOEXCEPT { // _Get_first 拿到的是自定义析构方法 //_Mypair._Get_second() 管理的指针 _Mypair._Get_first()(_Mypair._Get_second()); }
virtual void _Delete_this() _NOEXCEPT { // destroy self delete this; }
_Compressed_pair<_Dx, _Ty *> _Mypair; }; |
_Ref_count::_Delete_this
C++ template 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() _NOEXCEPT { // destroy managed resource delete _Ptr; }
virtual void _Delete_this() _NOEXCEPT { // destroy self delete this; }
_Ty * _Ptr; }; |
当shared ptr 创时候带了自定义析构函数会使用_Ref_count_del这个类
默认使用的是_Delete_this
通过上边分析可以看出,当智能指针的引用计数清0的时候首先会销毁ptr,其次在判断弱引用的技术是否也清0了,如果清0了就一并释放了
weak_ptr 分析
weak_ptr构造
C++ template class weak_ptr : public _Ptr_base<_Ty> { // class for pointer to reference counted resource public: typedef weak_ptr<_Ty> _Myt; typedef _Ptr_base<_Ty> _Mybase;
constexpr weak_ptr() _NOEXCEPT { // construct empty weak_ptr object }
weak_ptr(const weak_ptr& _Other) _NOEXCEPT { // construct weak_ptr object for resource pointed to by _Other this->_Resetw(_Other); } //is_convertible 会判断原weak_ptr持有的指针跟构造的指针是否同一个类型 //如果是同一个类型使用下边方法,不是会调用其他的构造芳芳 //这也就是SFINAE典型应用 template class = typename enable_if::value, void>::type> weak_ptr(const shared_ptr<_Ty2>& _Other) _NOEXCEPT { // construct weak_ptr object for resource owned by _Other this->_Resetw(_Other); } } |
通过shared_ptr构造weak_ptr 过程
_Ptr_base::_Resetw
C++ template class _Ptr_base { // base class for shared_ptr and weak_ptr void _Resetw() { // release weak reference to resource _Resetw((_Ty *)0, 0); } template void _Resetw(const _Ptr_base<_Ty2>& _Other) { // release weak reference to resource and take _Other._Ptr _Resetw(_Other._Ptr, _Other._Rep); } template void _Resetw(_Ty2 *_Other_ptr, _Ref_count_base *_Other_rep) { // point to _Other_ptr through _Other_rep if (_Other_rep) _Other_rep->_Incwref(); if (_Rep != 0) _Rep->_Decwref(); _Rep = _Other_rep; _Ptr = const_cast *>(_Other_ptr); } public: typedef _Ptr_base<_Ty> _Myt; typedef _Ty element_type; private: _Ty *_Ptr; _Ref_count_base *_Rep; } |
通过上边的_Resetw 可以发现 它是从shared_ptr中的_Ptr与_Rep 构建出来的,为了防止构建过程中出现野指针的情况,它以上来就会调用_Other_rep->_Incwref();增加一个引用计数
std::enable_shared_from_this
enable_shared_from_this 定义
C++ template class enable_shared_from_this { // provide member functions that create shared_ptr to this public: typedef _Ty _EStype;
shared_ptr<_Ty> shared_from_this() { // return shared_ptr return (shared_ptr<_Ty>(_Wptr)); }
shared_ptr shared_from_this() const { // return shared_ptr return (shared_ptr(_Wptr)); } private: weak_ptr<_Ty> _Wptr; } |