shared_ptr
Reference from https://www.jianshu.com/p/b6ac02d406a0
shared_ The PTR class does almost nothing. It inherits__ shared_ptr, __shared_ptr has a type of__ shared_ Member of type count_ M_refcount, __shared_count has an internal type of_ Sp_counted_base *_ M_ Members of PI_ Sp_counted_base is the whole shared_ The core of PTR function, through_ Sp_counted_base controls the reference count to manage managed memory, as can be seen from the figure_ Sp_ counted_ The pointer of managed memory is not held in base. Here__ shared_ The member inside count is actually a member inherited from_ Sp_counted_base_ Sp_counted_ptr type_ Sp_counted_ptr type holds a pointer to managed memory internally_ M_ptr, _M_pi is a_ Sp_counted_base base class object pointer to_ Sp_counted_ptr subclass object memory, so_ M_ Inside the PI, you can control the reference count and release the managed memory at last.
Here called_ M_ PI is the management object, which is internal_ M_ptr is a managed object, which manages multiple shared of the same managed object_ PTR internally shares a management object (_M_pi), where there are multiple shared objects_ PTR may be through the first shared_ptr is copied or moved, and there are two member variables in the management object_ M_use_count and_ M_weak_count, _M_use_count refers to the reference count of managed objects. It controls when managed objects are destructed and released. There are probably N shared objects_ The reference count of the copy of PTR is N. when the reference count is 0, the destructor of the managed object is called and the memory is released_ M_weak_count refers to the reference count of the management object. The management object is also a memory pointer, which is the first shared during initialization_ PTR comes from new, and it also needs to delete in the end, so it is used_ M_weak_count to control when the management object is destructed. We usually use weak_ptr actually holds the pointer of this management object, when weak_ Reference count of management object when PTR copy_ M_ weak_ The count will increase when_ M_ weak_ When count is 0, the management object_ M_ PI will destruct and free memory.
class shared_ptr
template <typename _Tp> class shared_ptr : public __shared_ptr<_Tp>
Member function
template <typename _Tp1> shared_ptr &operator=(const shared_ptr<_Tp1> &__r) noexcept { this->__shared_ptr<_Tp>::operator=(__r); return *this; }
class __shared_ptr
template <typename _Tp, _Lock_policy _Lp> class __shared_ptr
Member variable
_Tp *_M_ptr; // Contained pointer. __shared_count<_Lp> _M_refcount; // Reference counter.
Member function
// Overload assignment operator __shared_ptr &operator=(const __shared_ptr &) noexcept = default; template <typename _Tp1> __shared_ptr &operator=(const __shared_ptr<_Tp1, _Lp> &__r) noexcept { _M_ptr = __r._M_ptr; _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw return *this; } // Constructor template <typename _Tp1> explicit __shared_ptr(_Tp1 *__p) : _M_ptr(__p), _M_refcount(__p) { __glibcxx_function_requires( _ConvertibleConcept<_Tp1 *, _Tp *>) static_assert(sizeof(_Tp1) > 0, "incomplete type"); __enable_shared_from_this_helper(_M_refcount, __p, __p); } // Destructor ~__shared_ptr() = default;
class __shared_count
Member variable
_Sp_counted_base<_Lp> *_M_pi;//_ M_pi is a_ Sp_counted_base base class object pointer to_ Sp_counted_ptr subclass object memory, so_ M_ Inside the PI, you can control the reference count and release the managed memory at last.
Member function
// Constructor template <typename _Ptr> explicit __shared_count(_Ptr __p) : _M_pi(0) { __try { _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p); // _ M_pi pointing_ Sp_counted_ptr subclass object memory } __catch(...) { delete __p; __throw_exception_again; } } // Destructor ~__shared_count() noexcept { if (_M_pi != nullptr) _M_pi->_M_release(); } // Overload assignment operator __shared_count &operator=(const __shared_count &__r) noexcept { _Sp_counted_base<_Lp> *__tmp = __r._M_pi; if (__tmp != _M_pi) { if (__tmp != 0) __tmp->_M_add_ref_copy(); if (_M_pi != 0) _M_pi->_M_release(); _M_pi = __tmp; } return *this; } explicit operator bool() const // never throws { return _M_ptr == 0 ? false : true; }
class _Sp_counted_base
template <_Lock_policy _Lp = __default_lock_policy> class _Sp_counted_base : public _Mutex_base<_Lp>
Member variable
private: _Atomic_word _M_use_count; // #shared _Atomic_word _M_weak_count; // #weak + (#shared != 0)
Member function
_Sp_counted_base() noexcept : _M_use_count(1), _M_weak_count(1) {} //Note that when shared_ptr copy or move_ M_weak_count will not increase. It represents the count of management objects. Only when__ M_ use_ When count is 0_ M_weak_count will be reduced by 1. In addition_ M_ weak_ The value of count is determined by weak_ptr controlled. virtual ~_Sp_counted_base() noexcept {} void _M_add_ref_copy() { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); } void _M_release() noexcept { // Be race-detector-friendly. For more info see bits/c++config. _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count); if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1) { _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count); _M_dispose(); // There must be a memory barrier between dispose() and destroy() // to ensure that the effects of dispose() are observed in the // thread that runs destroy(). // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html if (_Mutex_base<_Lp>::_S_need_barriers) { _GLIBCXX_READ_MEM_BARRIER; _GLIBCXX_WRITE_MEM_BARRIER; } // Be race-detector-friendly. For more info see bits/c++config. _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count); if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1) { _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count); _M_destroy(); } } } void _M_weak_add_ref() noexcept { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); } void _M_weak_release() noexcept { // Be race-detector-friendly. For more info see bits/c++config. _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count); if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1) { _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count); if (_Mutex_base<_Lp>::_S_need_barriers) { // See _M_release(), // destroy() must observe results of dispose() _GLIBCXX_READ_MEM_BARRIER; _GLIBCXX_WRITE_MEM_BARRIER; } _M_destroy(); } }
class _Sp_counted_ptr
template <typename _Ptr, _Lock_policy _Lp> class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
Member variable
protected: _Ptr _M_ptr; // Pointer to managed memory
Member function
explicit _Sp_counted_ptr(_Ptr __p) : _M_ptr(__p) {} virtual void _M_dispose() noexcept { delete _M_ptr; } virtual void _M_destroy() noexcept { delete this; }
weak_ptr
Reference from https://www.jianshu.com/p/b6ac02d406a0
Note that when shared_ptr copy or move_ M_weak_count will not increase. It represents the count of management objects. Only when__ M_ use_ When count is 0_ M_weak_count will be reduced by 1. In addition_ M_ weak_ The value of count is determined by weak_ptr controlled.
weak_ptr internal and shared_ptr internally holds the same management object pointer, i.e_ Sp_ counted_ Pointer to base, when weak_ When PTR is assigned, copied and destructed_ Sp_counted_base internal_ M_weak_count will be added or subtracted accordingly. When_ M_ weak_ When count is 0, it means that the managed object is no longer needed to control the managed object. Call_ M_ delete this of destroy() to free the memory of the management object.
weak_ptr does not prolong the life cycle of the object pointed to by the native pointer. In fact, it is weak_ptr also has no constructor of native pointer, which can only be used by shared_ptr or weak_ptr is constructed. It is a pointer for the purpose of extending the life cycle.
class weak_ptr
template <typename _Tp> class weak_ptr : public __weak_ptr<_Tp>
Member function
template <typename _Tp1> weak_ptr &operator=(const weak_ptr<_Tp1> &__r) noexcept { this->__weak_ptr<_Tp>::operator=(__r); return *this; } template <typename _Tp1, typename = typename std::enable_if< std::is_convertible<_Tp1 *, _Tp *>::value>::type> weak_ptr(const weak_ptr<_Tp1> &__r) noexcept : __weak_ptr<_Tp>(__r) {} // Used to extend the life cycle shared_ptr<_Tp> lock() const noexcept { #ifdef __GTHREADS if (this->expired()) return shared_ptr<_Tp>(); __try { return shared_ptr<_Tp>(*this); } __catch(const bad_weak_ptr &) { return shared_ptr<_Tp>(); } #else return this->expired() ? shared_ptr<_Tp>() : shared_ptr<_Tp>(*this); #endif }
class __weak_ptr
template <typename _Tp, _Lock_policy _Lp> class __weak_ptr
Member variable
_Tp *_M_ptr; // Contained pointer. __weak_count<_Lp> _M_refcount; // Reference counter.
Member function
template <typename _Tp1, typename = typename std::enable_if< std::is_convertible<_Tp1 *, _Tp *>::value>::type> __weak_ptr(const __shared_ptr<_Tp1, _Lp> &__r) noexcept : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) {} template <typename _Tp1> __weak_ptr &operator=(const __weak_ptr<_Tp1, _Lp> &__r) noexcept { _M_ptr = __r.lock().get(); _M_refcount = __r._M_refcount; return *this; } __weak_ptr(const __weak_ptr &) noexcept = default; ~__weak_ptr() = default; bool expired() const noexcept { return _M_refcount._M_get_use_count() == 0; }
class __weak_count
template <_Lock_policy _Lp> class __weak_count
Member variable
_Sp_counted_base<_Lp> *_M_pi;
Member function
__weak_count(const __weak_count<_Lp> &__r) noexcept : _M_pi(__r._M_pi) { if (_M_pi != 0) _M_pi->_M_weak_add_ref(); } __weak_count<_Lp> &operator=(const __weak_count<_Lp> &__r) noexcept { _Sp_counted_base<_Lp> *__tmp = __r._M_pi; if (__tmp != 0) __tmp->_M_weak_add_ref(); if (_M_pi != 0) _M_pi->_M_weak_release(); _M_pi = __tmp; return *this; } ~__weak_count() noexcept { if (_M_pi != 0) _M_pi->_M_weak_release(); }