一、shared_ptr的内存结构
![在这里插入图片描述](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
结构解释:
- _Ptr和_Ref分别保存存放在堆区空间的被管理对象和引用计数结构
- 引用计数结构中的_rptr也保存被管理对象的地址。
- _Users记录shared_ptr指针管理对象的个数
- _Weaks记录weak_ptr管理对象的个数
二、删除器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| template<class _Ty> class Deleter { Deleter() = default; public: void operator()(_Ty* p = NULL)const { if (p != NULL) { delete p; } } };
template<class _Ty> class Deleter<_Ty[]> { Deleter() = default; public: void operator()(_Ty* p = NULL)const { if (p != NULL) { delete[] p; } } };
|
三、引用计数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| template<class _Ty> class Rfc { private: _Ty* _rPtr; atomic_int _Users; atomic_int _Weaks; public: Rfc(_Ty* p = NULL) :_rPtr(p), _Users(1), _Weaks(1) {} ~Rfc() {} void IncRef_Users() { ++_Users; } void IncRef_Weaks() { ++_Weaks; } };
|
四、shared_ptr仿写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| template<class _Ty, class Deleter_T = Deleter<_Ty>> class shared_ptr { private: _Ty* _Ptr; Rfc<_Ty>* _Ref; Deleter_T _deleter;
public: shared_ptr(_Ty* p = NULL) : _Ptr(p), _Ref(NULL) { if (_Ptr != NULL) { __Ref = new Rfc<_Ty>(p); } } shared_ptr(const shared_ptr& src): _Ptr(src._Ptr), _Ref(src._Ref) { if (_Ref != NULL) { _Ref->Incref_Users(); } } shared_ptr(shared_ptr&& rval): _Ptr(rval._Ptr), _Ref(rval._Ref) { rval._Ptr = NULL; rval._Ref = NULL; } shared_ptr& operator=(const shared_ptr& src) { if (this == &src || _Ptr == src._Ptr) return *this; if (_Ptr != NULL && --_Ref->_Users == 0) { _deleter(_Ptr); if (--_Ref->_Weaks == 0) { delete _Ref; } } _Ptr = src._Ptr; _Ref = src._Ref; if (_Ptr != NULL) { _Ref->IncRef_Users(); } return *this; } shared_ptr& operator=(shared_ptr&& rval) { if (this == &rval) return *this; if (_Ptr != NULL && rval._Ptr != NULL && _Ptr == rval._Ptr) { --_Ref->_Users; rval._Ptr = NULL; rval._Ref = NULL; return *this; } if (_Ptr != NULL && --_Ref->_Users == 0) { _deleter(_Ptr); if (--_Ref->_Weaks == 0) { delete _Ref; } } _Ptr = rval._Ptr; _Ref = rval._Ref; rval._Ptr = NULL; rval._Ref = NULL; return *this; }
~shared_ptr() { if (_Ref != NULL && --_Ref->_Users == 0) { _deleter(_Ptr); if (--_Ref->_Weaks == 0) { delete _Ref; } } }
_Ty* get()const { return _Ptr; } _Ty* operator->() { return get(); } _Ty& operator*() { return *get(); } size_t use_count()const { return _Ref->_Users; } void swap(shared_ptr& src) { std::swap(_Ptr, src._Ptr); std::swap(_Ref, src._Ref); } operator bool()const { return _Ptr != NULL; } private: friend class weak_ptr<_Ty>; };
|
五、关于weak_ptr
定义于头文件
1 2 3
| template< class T > class weak_ptr;
|
std::weak_ptr 是一种智能指针,它对被 std::shared_ptr 管理的对象存在非拥有性(「弱」)引用。在访问所引用的对象前必须先转换为 std::shared_ptr。
std::weak_ptr 用来表达临时所有权的概念:当某个对象只有存在时才需要被访问,而且随时可能被他人删除时,可以使用 std::weak_ptr 来跟踪该对象。需要获得临时所有权时,则将其转换为 std::shared_ptr,此时如果原来的 std::shared_ptr 被销毁,则该对象的生命期将被延长至这个临时的 std::shared_ptr 同样被销毁为止。
std::weak_ptr 的另一用法是打断 std::shared_ptr 所管理的对象组成的环状引用。若这种环被孤立(例如无指向环中的外部共享指针),则 shared_ptr 引用计数无法抵达零,而内存被泄露。能令环中的指针之一为弱指针以避免此情况。
六、weak_ptr与shared_ptr关联内存结构
![在这里插入图片描述](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
七、weak_ptr仿写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| template<class _Ty> class weak_ptr { private: Rfc<_Ty>* _Rp; public: weak_ptr(Rfc<_Ty>* p = NULL) : _Rp(p) {} weak_ptr(const shared_ptr<_Ty>& src) : _Rp(src._Ref) { if (_Rp != NULL) { _Rp->IncRef_Weaks(); } } weak_ptr(const weak_ptr& src) : _Rp(src._Ref) { if (_Rp != NULL) { _Rp->IncRef_Weaks(); } } ~weak_ptr() { if (_Rp != NULL && --_Rp->_Weaks == 0) { delete _Rp; } } weak_ptr& operator=(const weak_ptr& src) { if (this == &src || _Rp == src._Rp) return *this; if (_Rp != NULL && --_Rp->_Weaks == 0) { delete _Rp; } _Rp = src._Rp; if (_Rp != NULL) { _Rp->IncRef_Weaks(); } return *this; } weak_ptr& operator=(weak_ptr&& rval) { if (this == &rval || _Rp == rval._Rp) return *this; if (_Rp != NULL && rval._Rp != NULL && _Rp == rval._Rp) { --_Rp->_Weaks; rval._Rp = NULL; return *this; } if (_Rp != NULL && --_Rp->_Weaks == 0) { delete _Rp; } _Rp = rval._Rp; rval._Rp = NULL; return *this; }
weak_ptr& operator=(const shared_ptr<_Ty>& src) { if (_Rp != NULL && --_Rp->_Weaks == 0) { delete _Rp; } _Rp = src._Ref; if (_Rp != NULL) { _Rp->IncRef_Weaks(); } return *this; } weak_ptr& operator=(shared_ptr<_Ty>&& rval) = delete;
bool expired()const { return _Rp->_Users == 0; } void swap(weak_ptr& src) { std::swap(_Rp, src._Rp); } shared_ptr<_Ty> lock() { shared_ptr<_Ty> tmp; tmp._Ptr = _Rp->_rPtr; tmp._Ref = _Rp; tmp._Ref->IncRef_Users(); return tmp; } };
|