-
共享指针
-
说明
-
shared_ptr
类提供类的行为接口. -
有专门的父类提供数据管理接口.
-
-
实现
-
涉及到继承,以及引用计数是否需要多线程安全.
-
控制块的类型.
-
-
-
源码
-
shared_ptr
template<typename _Tp>class shared_ptr : public __shared_ptr<_Tp>{ template<typename... _Args>using _Constructible = typename enable_if<is_constructible<__shared_ptr<_Tp>, _Args...>::value>::type;template<typename _Arg>using _Assignable = typename enable_if<is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&>::type;public:using element_type = typename __shared_ptr<_Tp>::element_type;#if __cplusplus > 201402L # define __cpp_lib_shared_ptr_weak_type 201606using weak_type = weak_ptr<_Tp>; #endif/*** @brief Construct an empty %shared_ptr.* @post use_count()==0 && get()==0*/constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }shared_ptr(const shared_ptr&) noexcept = default;/*** @brief Construct a %shared_ptr that owns the pointer @a __p.* @param __p A pointer that is convertible to element_type*.* @post use_count() == 1 && get() == __p* @throw std::bad_alloc, in which case @c delete @a __p is called.*/template<typename _Yp, typename = _Constructible<_Yp*>>explicitshared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }/*** @brief Construct a %shared_ptr that owns the pointer @a __p* and the deleter @a __d.* @param __p A pointer.* @param __d A deleter.* @post use_count() == 1 && get() == __p* @throw std::bad_alloc, in which case @a __d(__p) is called.** Requirements: _Deleter's copy constructor and destructor must* not throw** __shared_ptr will release __p by calling __d(__p)*/template<typename _Yp, typename _Deleter,typename = _Constructible<_Yp*, _Deleter>>shared_ptr(_Yp* __p, _Deleter __d): __shared_ptr<_Tp>(__p, std::move(__d)) { }/*** @brief Construct a %shared_ptr that owns a null pointer* and the deleter @a __d.* @param __p A null pointer constant.* @param __d A deleter.* @post use_count() == 1 && get() == __p* @throw std::bad_alloc, in which case @a __d(__p) is called.** Requirements: _Deleter's copy constructor and destructor must* not throw** The last owner will call __d(__p)*/template<typename _Deleter>shared_ptr(nullptr_t __p, _Deleter __d): __shared_ptr<_Tp>(__p, std::move(__d)) { }/*** @brief Construct a %shared_ptr that owns the pointer @a __p* and the deleter @a __d.* @param __p A pointer.* @param __d A deleter.* @param __a An allocator.* @post use_count() == 1 && get() == __p* @throw std::bad_alloc, in which case @a __d(__p) is called.** Requirements: _Deleter's copy constructor and destructor must* not throw _Alloc's copy constructor and destructor must not* throw.** __shared_ptr will release __p by calling __d(__p)*/template<typename _Yp, typename _Deleter, typename _Alloc,typename = _Constructible<_Yp*, _Deleter, _Alloc>>shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a): __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }/*** @brief Construct a %shared_ptr that owns a null pointer* and the deleter @a __d.* @param __p A null pointer constant.* @param __d A deleter.* @param __a An allocator.* @post use_count() == 1 && get() == __p* @throw std::bad_alloc, in which case @a __d(__p) is called.** Requirements: _Deleter's copy constructor and destructor must* not throw _Alloc's copy constructor and destructor must not* throw.** The last owner will call __d(__p)*/template<typename _Deleter, typename _Alloc>shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a): __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }// Aliasing constructor/*** @brief Constructs a %shared_ptr instance that stores @a __p* and shares ownership with @a __r.* @param __r A %shared_ptr.* @param __p A pointer that will remain valid while @a *__r is valid.* @post get() == __p && use_count() == __r.use_count()** This can be used to construct a @c shared_ptr to a sub-object* of an object managed by an existing @c shared_ptr.** @code* shared_ptr< pair<int,int> > pii(new pair<int,int>());* shared_ptr<int> pi(pii, &pii->first);* assert(pii.use_count() == 2);* @endcode*/template<typename _Yp>shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept: __shared_ptr<_Tp>(__r, __p) { }/*** @brief If @a __r is empty, constructs an empty %shared_ptr;* otherwise construct a %shared_ptr that shares ownership* with @a __r.* @param __r A %shared_ptr.* @post get() == __r.get() && use_count() == __r.use_count()*/template<typename _Yp,typename = _Constructible<const shared_ptr<_Yp>&>>shared_ptr(const shared_ptr<_Yp>& __r) noexcept: __shared_ptr<_Tp>(__r) { }/*** @brief Move-constructs a %shared_ptr instance from @a __r.* @param __r A %shared_ptr rvalue.* @post *this contains the old value of @a __r, @a __r is empty.*/shared_ptr(shared_ptr&& __r) noexcept: __shared_ptr<_Tp>(std::move(__r)) { }/*** @brief Move-constructs a %shared_ptr instance from @a __r.* @param __r A %shared_ptr rvalue.* @post *this contains the old value of @a __r, @a __r is empty.*/template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>shared_ptr(shared_ptr<_Yp>&& __r) noexcept: __shared_ptr<_Tp>(std::move(__r)) { }/*** @brief Constructs a %shared_ptr that shares ownership with @a __r* and stores a copy of the pointer stored in @a __r.* @param __r A weak_ptr.* @post use_count() == __r.use_count()* @throw bad_weak_ptr when __r.expired(),* in which case the constructor has no effect.*/template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>explicit shared_ptr(const weak_ptr<_Yp>& __r): __shared_ptr<_Tp>(__r) { }#if _GLIBCXX_USE_DEPRECATED #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations"template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>shared_ptr(auto_ptr<_Yp>&& __r); #pragma GCC diagnostic pop #endif// _GLIBCXX_RESOLVE_LIB_DEFECTS// 2399. shared_ptr's constructor from unique_ptr should be constrainedtemplate<typename _Yp, typename _Del,typename = _Constructible<unique_ptr<_Yp, _Del>>>shared_ptr(unique_ptr<_Yp, _Del>&& __r): __shared_ptr<_Tp>(std::move(__r)) { }#if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED// This non-standard constructor exists to support conversions that// were possible in C++11 and C++14 but are ill-formed in C++17.// If an exception is thrown this constructor has no effect.template<typename _Yp, typename _Del,_Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0>shared_ptr(unique_ptr<_Yp, _Del>&& __r): __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { } #endif/*** @brief Construct an empty %shared_ptr.* @post use_count() == 0 && get() == nullptr*/constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }shared_ptr& operator=(const shared_ptr&) noexcept = default;template<typename _Yp>_Assignable<const shared_ptr<_Yp>&>operator=(const shared_ptr<_Yp>& __r) noexcept{ this->__shared_ptr<_Tp>::operator=(__r);return *this;}#if _GLIBCXX_USE_DEPRECATED #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations"template<typename _Yp>_Assignable<auto_ptr<_Yp>>operator=(auto_ptr<_Yp>&& __r){ this->__shared_ptr<_Tp>::operator=(std::move(__r));return *this;} #pragma GCC diagnostic pop #endifshared_ptr&operator=(shared_ptr&& __r) noexcept{ this->__shared_ptr<_Tp>::operator=(std::move(__r));return *this;}template<class _Yp>_Assignable<shared_ptr<_Yp>>operator=(shared_ptr<_Yp>&& __r) noexcept{ this->__shared_ptr<_Tp>::operator=(std::move(__r));return *this;}template<typename _Yp, typename _Del>_Assignable<unique_ptr<_Yp, _Del>>operator=(unique_ptr<_Yp, _Del>&& __r){ this->__shared_ptr<_Tp>::operator=(std::move(__r));return *this;}private:// This constructor is non-standard, it is used by allocate_shared.template<typename _Alloc, typename... _Args>shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,_Args&&... __args): __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...){ }template<typename _Yp, typename _Alloc, typename... _Args>friend shared_ptr<_Yp>allocate_shared(const _Alloc& __a, _Args&&... __args);// This constructor is non-standard, it is used by weak_ptr::lock().shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t): __shared_ptr<_Tp>(__r, std::nothrow) { }friend class weak_ptr<_Tp>;};
-
可以看到父类
__shared_ptr
,shared_ptr
没有提供任何成员变量.
-
-
说明
-
提供的都是一些数据操作函数.
-
-
-
数据类
-
源码
template<typename _Tp, _Lock_policy _Lp>class __shared_ptr: public __shared_ptr_access<_Tp, _Lp>{ public:using element_type = typename remove_extent<_Tp>::type;private:// Constraint for taking ownership of a pointer of type _Yp*:template<typename _Yp>using _SafeConv= typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;// Constraint for construction from shared_ptr and weak_ptr:template<typename _Yp, typename _Res = void>using _Compatible = typenameenable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;// Constraint for assignment from shared_ptr and weak_ptr:template<typename _Yp>using _Assignable = _Compatible<_Yp, __shared_ptr&>;// Constraint for construction from unique_ptr:template<typename _Yp, typename _Del, typename _Res = void,typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>using _UniqCompatible = typename enable_if<__and_<__sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*>>::value, _Res>::type;// Constraint for assignment from unique_ptr:template<typename _Yp, typename _Del>using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;public:#if __cplusplus > 201402Lusing weak_type = __weak_ptr<_Tp, _Lp>; #endifconstexpr __shared_ptr() noexcept: _M_ptr(0), _M_refcount(){ }template<typename _Yp, typename = _SafeConv<_Yp>>explicit__shared_ptr(_Yp* __p): _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type()){ static_assert( !is_void<_Yp>::value, "incomplete type" );static_assert( sizeof(_Yp) > 0, "incomplete type" );_M_enable_shared_from_this_with(__p);}template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>__shared_ptr(_Yp* __p, _Deleter __d): _M_ptr(__p), _M_refcount(__p, std::move(__d)){ static_assert(__is_invocable<_Deleter&, _Yp*&>::value,"deleter expression d(p) is well-formed");_M_enable_shared_from_this_with(__p);}template<typename _Yp, typename _Deleter, typename _Alloc,typename = _SafeConv<_Yp>>__shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a): _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a)){ static_assert(__is_invocable<_Deleter&, _Yp*&>::value,"deleter expression d(p) is well-formed");_M_enable_shared_from_this_with(__p);}template<typename _Deleter>__shared_ptr(nullptr_t __p, _Deleter __d): _M_ptr(0), _M_refcount(__p, std::move(__d)){ }template<typename _Deleter, typename _Alloc>__shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a): _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a)){ }template<typename _Yp>__shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,element_type* __p) noexcept: _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws{ }__shared_ptr(const __shared_ptr&) noexcept = default;__shared_ptr& operator=(const __shared_ptr&) noexcept = default;~__shared_ptr() = default;template<typename _Yp, typename = _Compatible<_Yp>>__shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount){ }__shared_ptr(__shared_ptr&& __r) noexcept: _M_ptr(__r._M_ptr), _M_refcount(){ _M_refcount._M_swap(__r._M_refcount);__r._M_ptr = 0;}template<typename _Yp, typename = _Compatible<_Yp>>__shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept: _M_ptr(__r._M_ptr), _M_refcount(){ _M_refcount._M_swap(__r._M_refcount);__r._M_ptr = 0;}template<typename _Yp, typename = _Compatible<_Yp>>explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r): _M_refcount(__r._M_refcount) // may throw{ // It is now safe to copy __r._M_ptr, as// _M_refcount(__r._M_refcount) did not throw._M_ptr = __r._M_ptr;}// If an exception is thrown this constructor has no effect.template<typename _Yp, typename _Del,typename = _UniqCompatible<_Yp, _Del>>__shared_ptr(unique_ptr<_Yp, _Del>&& __r): _M_ptr(__r.get()), _M_refcount(){ auto __raw = __to_address(__r.get());_M_refcount = __shared_count<_Lp>(std::move(__r));_M_enable_shared_from_this_with(__raw);}#if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATEDprotected:// If an exception is thrown this constructor has no effect.template<typename _Tp1, typename _Del,typename enable_if<__and_<__not_<is_array<_Tp>>, is_array<_Tp1>,is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*>>::value, bool>::type = true>__shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete): _M_ptr(__r.get()), _M_refcount(){ auto __raw = __to_address(__r.get());_M_refcount = __shared_count<_Lp>(std::move(__r));_M_enable_shared_from_this_with(__raw);}public: #endif#if _GLIBCXX_USE_DEPRECATED #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations"// Postcondition: use_count() == 1 and __r.get() == 0template<typename _Yp, typename = _Compatible<_Yp>>__shared_ptr(auto_ptr<_Yp>&& __r); #pragma GCC diagnostic pop #endifconstexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }template<typename _Yp>_Assignable<_Yp>operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept{ _M_ptr = __r._M_ptr;_M_refcount = __r._M_refcount; // __shared_count::op= doesn't throwreturn *this;}#if _GLIBCXX_USE_DEPRECATED #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations"template<typename _Yp>_Assignable<_Yp>operator=(auto_ptr<_Yp>&& __r){ __shared_ptr(std::move(__r)).swap(*this);return *this;} #pragma GCC diagnostic pop #endif__shared_ptr&operator=(__shared_ptr&& __r) noexcept{ __shared_ptr(std::move(__r)).swap(*this);return *this;}template<class _Yp>_Assignable<_Yp>operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept{ __shared_ptr(std::move(__r)).swap(*this);return *this;}template<typename _Yp, typename _Del>_UniqAssignable<_Yp, _Del>operator=(unique_ptr<_Yp, _Del>&& __r){ __shared_ptr(std::move(__r)).swap(*this);return *this;}voidreset() noexcept{ __shared_ptr().swap(*this); }template<typename _Yp>_SafeConv<_Yp>reset(_Yp* __p) // _Yp must be complete.{ // Catch self-reset errors.__glibcxx_assert(__p == 0 || __p != _M_ptr);__shared_ptr(__p).swap(*this);}template<typename _Yp, typename _Deleter>_SafeConv<_Yp>reset(_Yp* __p, _Deleter __d){ __shared_ptr(__p, std::move(__d)).swap(*this); }template<typename _Yp, typename _Deleter, typename _Alloc>_SafeConv<_Yp>reset(_Yp* __p, _Deleter __d, _Alloc __a){ __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); }element_type*get() const noexcept{ return _M_ptr; }explicit operator bool() const // never throws{ return _M_ptr == 0 ? false : true; }boolunique() const noexcept{ return _M_refcount._M_unique(); }longuse_count() const noexcept{ return _M_refcount._M_get_use_count(); }voidswap(__shared_ptr<_Tp, _Lp>& __other) noexcept{ std::swap(_M_ptr, __other._M_ptr);_M_refcount._M_swap(__other._M_refcount);}template<typename _Tp1>boolowner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept{ return _M_refcount._M_less(__rhs._M_refcount); }template<typename _Tp1>boolowner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept{ return _M_refcount._M_less(__rhs._M_refcount); }protected:// This constructor is non-standard, it is used by allocate_shared.template<typename _Alloc, typename... _Args>__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,_Args&&... __args): _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,std::forward<_Args>(__args)...){ // _M_ptr needs to point to the newly constructed object.// This relies on _Sp_counted_ptr_inplace::_M_get_deleter. #if __cpp_rttivoid* __p = _M_refcount._M_get_deleter(typeid(__tag)); #elsevoid* __p = _M_refcount._M_get_deleter(_Sp_make_shared_tag::_S_ti()); #endif_M_ptr = static_cast<_Tp*>(__p);_M_enable_shared_from_this_with(_M_ptr);}template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,typename... _Args>friend __shared_ptr<_Tp1, _Lp1>__allocate_shared(const _Alloc& __a, _Args&&... __args);// This constructor is used by __weak_ptr::lock() and// shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).__shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t): _M_refcount(__r._M_refcount, std::nothrow){ _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;}friend class __weak_ptr<_Tp, _Lp>;private:template<typename _Yp>using __esft_base_t = decltype(__enable_shared_from_this_base(std::declval<const __shared_count<_Lp>&>(),std::declval<_Yp*>()));// Detect an accessible and unambiguous enable_shared_from_this base.template<typename _Yp, typename = void>struct __has_esft_base: false_type { };template<typename _Yp>struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>: __not_<is_array<_Tp>> { }; // No enable shared_from_this for arraystemplate<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>typename enable_if<__has_esft_base<_Yp2>::value>::type_M_enable_shared_from_this_with(_Yp* __p) noexcept{ if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))__base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);}template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>typename enable_if<!__has_esft_base<_Yp2>::value>::type_M_enable_shared_from_this_with(_Yp*) noexcept{ }void*_M_get_deleter(const std::type_info& __ti) const noexcept{ return _M_refcount._M_get_deleter(__ti); }template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;template<typename _Del, typename _Tp1, _Lock_policy _Lp1>friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;template<typename _Del, typename _Tp1>friend _Del* get_deleter(const shared_ptr<_Tp1>&) noexcept;element_type* _M_ptr; // Contained pointer.__shared_count<_Lp> _M_refcount; // Reference counter.};
-
_Tp
是数据类型._Lp
是互斥机制. -
_Lp
决定了是否多线程安全.
-
-
数据
-
一个数据指针和引用计数
__shared_count<_Lp>
. -
通过构造可以看到,数据指针也会传入数据指针.
-
-
_Lock_policy
enum _Lock_policy { _S_single, _S_mutex, _S_atomic };
-
可以看到是枚举类型.
-
-
-
引用计数管理
__shared_count
-
说明
- 作用就是引用计数.
-
源码
template<_Lock_policy _Lp>class __shared_count{ public:constexpr __shared_count() noexcept : _M_pi(0){ }template<typename _Ptr>explicit__shared_count(_Ptr __p) : _M_pi(0){ __try{ _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);}__catch(...){ delete __p;__throw_exception_again;}}template<typename _Ptr>__shared_count(_Ptr __p, /* is_array = */ false_type): __shared_count(__p){ }template<typename _Ptr>__shared_count(_Ptr __p, /* is_array = */ true_type): __shared_count(__p, __sp_array_delete{ }, allocator<void>()){ }template<typename _Ptr, typename _Deleter>__shared_count(_Ptr __p, _Deleter __d): __shared_count(__p, std::move(__d), allocator<void>()){ }template<typename _Ptr, typename _Deleter, typename _Alloc>__shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0){ typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;__try{ typename _Sp_cd_type::__allocator_type __a2(__a);auto __guard = std::__allocate_guarded(__a2);_Sp_cd_type* __mem = __guard.get();::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));_M_pi = __mem;__guard = nullptr;}__catch(...){ __d(__p); // Call _Deleter on __p.__throw_exception_again;}}template<typename _Tp, typename _Alloc, typename... _Args>__shared_count(_Sp_make_shared_tag, _Tp*, const _Alloc& __a,_Args&&... __args): _M_pi(0){ typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;typename _Sp_cp_type::__allocator_type __a2(__a);auto __guard = std::__allocate_guarded(__a2);_Sp_cp_type* __mem = __guard.get();::new (__mem) _Sp_cp_type(std::move(__a),std::forward<_Args>(__args)...);_M_pi = __mem;__guard = nullptr;}#if _GLIBCXX_USE_DEPRECATED #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations"// Special case for auto_ptr<_Tp> to provide the strong guarantee.template<typename _Tp>explicit__shared_count(std::auto_ptr<_Tp>&& __r); #pragma GCC diagnostic pop #endif// Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.template<typename _Tp, typename _Del>explicit__shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0){ // _GLIBCXX_RESOLVE_LIB_DEFECTS// 2415. Inconsistency between unique_ptr and shared_ptrif (__r.get() == nullptr)return;using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;using _Del2 = typename conditional<is_reference<_Del>::value,reference_wrapper<typename remove_reference<_Del>::type>,_Del>::type;using _Sp_cd_type= _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;using _Alloc = allocator<_Sp_cd_type>;using _Alloc_traits = allocator_traits<_Alloc>;_Alloc __a;_Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);_Alloc_traits::construct(__a, __mem, __r.release(),__r.get_deleter()); // non-throwing_M_pi = __mem;}// Throw bad_weak_ptr when __r._M_get_use_count() == 0.explicit __shared_count(const __weak_count<_Lp>& __r);// Does not throw if __r._M_get_use_count() == 0, caller must check.explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);~__shared_count() noexcept{ if (_M_pi != nullptr)_M_pi->_M_release();}__shared_count(const __shared_count& __r) noexcept: _M_pi(__r._M_pi){ if (_M_pi != 0)_M_pi->_M_add_ref_copy();}__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;}void_M_swap(__shared_count& __r) noexcept{ _Sp_counted_base<_Lp>* __tmp = __r._M_pi;__r._M_pi = _M_pi;_M_pi = __tmp;}long_M_get_use_count() const noexcept{ return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }bool_M_unique() const noexcept{ return this->_M_get_use_count() == 1; }void*_M_get_deleter(const std::type_info& __ti) const noexcept{ return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }bool_M_less(const __shared_count& __rhs) const noexcept{ return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }bool_M_less(const __weak_count<_Lp>& __rhs) const noexcept{ return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }// Friend function injected into enclosing namespace and found by ADLfriend inline booloperator==(const __shared_count& __a, const __shared_count& __b) noexcept{ return __a._M_pi == __b._M_pi; }private:friend class __weak_count<_Lp>;_Sp_counted_base<_Lp>* _M_pi;};
-
可以看到是一个指针类型,指针类型指向的是一个多肽类.
-
有好几种子类. 分别对应默认析构类型,自定义析构类型,
make_shared
类型.
-
-
说明
-
仅仅一个指针.
-
其他的则是引用计数的操作.
-
-
须知
-
析构函数会负责数据的析构和引用计数的管理.
-
-
_Sp_counted_base
的多态-
根据构造时的入参不同选用不同的计数器.
-
原始指针,默认析构.
template<typename _Ptr>explicit__shared_count(_Ptr __p) : _M_pi(0){ __try{ _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);}__catch(...){ delete __p;__throw_exception_again;}}
-
自定义析构,使用的
_Sp_counted_ptr
;
template<typename _Ptr, typename _Deleter>__shared_count(_Ptr __p, _Deleter __d): __shared_count(__p, std::move(__d), allocator<void>()){ }template<typename _Ptr, typename _Deleter, typename _Alloc>__shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0){ typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;__try{ typename _Sp_cd_type::__allocator_type __a2(__a);auto __guard = std::__allocate_guarded(__a2);_Sp_cd_type* __mem = __guard.get();::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));_M_pi = __mem;__guard = nullptr;}__catch(...){ __d(__p); // Call _Deleter on __p.__throw_exception_again;}}
-
析构函数,使用的是
_Sp_counted_deleter
.
template<typename _Tp, typename _Alloc, typename... _Args>__shared_count(_Sp_make_shared_tag, _Tp*, const _Alloc& __a,_Args&&... __args): _M_pi(0){ typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;typename _Sp_cp_type::__allocator_type __a2(__a);auto __guard = std::__allocate_guarded(__a2);_Sp_cp_type* __mem = __guard.get();::new (__mem) _Sp_cp_type(std::move(__a),std::forward<_Args>(__args)...);_M_pi = __mem;__guard = nullptr;}
-
make_shared
创建的使用的是_Sp_counted_ptr_inplace
.
-
-
-
计数数据的实现基类
-
代码
template<_Lock_policy _Lp = __default_lock_policy>class _Sp_counted_base: public _Mutex_base<_Lp>{ public:_Sp_counted_base() noexcept: _M_use_count(1), _M_weak_count(1) { }virtual~_Sp_counted_base() noexcept{ }// Called when _M_use_count drops to zero, to release the resources// managed by *this.virtual void_M_dispose() noexcept = 0;// Called when _M_weak_count drops to zero.virtual void_M_destroy() noexcept{ delete this; }virtual void*_M_get_deleter(const std::type_info&) noexcept = 0;void_M_add_ref_copy(){ __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }void_M_add_ref_lock();bool_M_add_ref_lock_nothrow();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.htmlif (_Mutex_base<_Lp>::_S_need_barriers){ __atomic_thread_fence (__ATOMIC_ACQ_REL);}// 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()__atomic_thread_fence (__ATOMIC_ACQ_REL);}_M_destroy();}}long_M_get_use_count() const noexcept{ // No memory barrier is used here so there is no synchronization// with other threads.return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED);}private:_Sp_counted_base(_Sp_counted_base const&) = delete;_Sp_counted_base& operator=(_Sp_counted_base const&) = delete;_Atomic_word _M_use_count; // #shared_Atomic_word _M_weak_count; // #weak + (#shared != 0)};
-
说明
-
首先有两个数据,共享计数和弱引用计数.
-
那么,怎么操作这个引用计数呢.
-
-
成员函数的实现
template<>inline void_Sp_counted_base<_S_single>::_M_add_ref_lock(){ if (_M_use_count == 0)__throw_bad_weak_ptr();++_M_use_count;}template<>inline void_Sp_counted_base<_S_mutex>::_M_add_ref_lock(){ __gnu_cxx::__scoped_lock sentry(*this);if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0){ _M_use_count = 0;__throw_bad_weak_ptr();}}template<>inline void_Sp_counted_base<_S_atomic>::_M_add_ref_lock(){ // Perform lock-free add-if-not-zero operation._Atomic_word __count = _M_get_use_count();do{ if (__count == 0)__throw_bad_weak_ptr();// Replace the current counter value with the old value + 1, as// long as it's not changed meanwhile.}while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,true, __ATOMIC_ACQ_REL,__ATOMIC_RELAXED));}template<>inline bool_Sp_counted_base<_S_single>::_M_add_ref_lock_nothrow(){ if (_M_use_count == 0)return false;++_M_use_count;return true;}template<>inline bool_Sp_counted_base<_S_mutex>::_M_add_ref_lock_nothrow(){ __gnu_cxx::__scoped_lock sentry(*this);if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0){ _M_use_count = 0;return false;}return true;}template<>inline bool_Sp_counted_base<_S_atomic>::_M_add_ref_lock_nothrow(){ // Perform lock-free add-if-not-zero operation._Atomic_word __count = _M_get_use_count();do{ if (__count == 0)return false;// Replace the current counter value with the old value + 1, as// long as it's not changed meanwhile.}while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,true, __ATOMIC_ACQ_REL,__ATOMIC_RELAXED));return true;}template<>inline void_Sp_counted_base<_S_single>::_M_add_ref_copy(){ ++_M_use_count; }template<>inline void_Sp_counted_base<_S_single>::_M_release() noexcept{ if (--_M_use_count == 0){ _M_dispose();if (--_M_weak_count == 0)_M_destroy();}}template<>inline void_Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept{ ++_M_weak_count; }template<>inline void_Sp_counted_base<_S_single>::_M_weak_release() noexcept{ if (--_M_weak_count == 0)_M_destroy();}template<>inline long_Sp_counted_base<_S_single>::_M_get_use_count() const noexcept{ return _M_use_count; }
-
根据各种特例化实现.
-
可以实现多种多线程安全机制.
-
枷锁,互斥,或者是单线程的
++,--
.
-
-
父类
// Empty helper class except when the template argument is _S_mutex.template<_Lock_policy _Lp>class _Mutex_base{ protected:// The atomic policy uses fully-fenced builtins, single doesn't care.enum { _S_need_barriers = 0 };};template<>class _Mutex_base<_S_mutex>: public __gnu_cxx::__mutex{ protected:// This policy is used when atomic builtins are not available.// The replacement atomic operations might not have the necessary// memory barriers.enum { _S_need_barriers = 1 };};
-
可以看到
mutex
和atomic
版本. -
普通版不需要.
-
-
-
计数数据的实现: 多态子类
-
说明
-
主要是用来适配不同的析构.
-
-
默认
template<typename _Ptr, _Lock_policy _Lp>class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>{ public:explicit_Sp_counted_ptr(_Ptr __p) noexcept: _M_ptr(__p) { }virtual void_M_dispose() noexcept{ delete _M_ptr; }virtual void_M_destroy() noexcept{ delete this; }virtual void*_M_get_deleter(const std::type_info&) noexcept{ return nullptr; }_Sp_counted_ptr(const _Sp_counted_ptr&) = delete;_Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;private:_Ptr _M_ptr;};
-
实现了虚函数析构器和释放自己的方式.
-
默认都是
delete
.
-
-
自定义析构
// Support for custom deleter and/or allocatortemplate<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>{ class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>{ typedef _Sp_ebo_helper<0, _Deleter> _Del_base;typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;public:_Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept: _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a){ }_Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }_Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }_Ptr _M_ptr;};public:using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;// __d(__p) must not throw._Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept: _M_impl(__p, std::move(__d), _Alloc()) { }// __d(__p) must not throw._Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept: _M_impl(__p, std::move(__d), __a) { }~_Sp_counted_deleter() noexcept { }virtual void_M_dispose() noexcept{ _M_impl._M_del()(_M_impl._M_ptr); }virtual void_M_destroy() noexcept{ __allocator_type __a(_M_impl._M_alloc());__allocated_ptr<__allocator_type> __guard_ptr{ __a, this };this->~_Sp_counted_deleter();}virtual void*_M_get_deleter(const std::type_info& __ti) noexcept{ #if __cpp_rtti// _GLIBCXX_RESOLVE_LIB_DEFECTS// 2400. shared_ptr's get_deleter() should use addressof()return __ti == typeid(_Deleter)? std::__addressof(_M_impl._M_del()): nullptr; #elsereturn nullptr; #endif}private:_Impl _M_impl;};
-
可以看到,实现的虚函数,数据析构和自我析构的实现不一样.
-
自定义析构函数析构.
-
-
make_shared
template<typename _Tp, typename _Alloc, _Lock_policy _Lp>class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>{ class _Impl : _Sp_ebo_helper<0, _Alloc>{ typedef _Sp_ebo_helper<0, _Alloc> _A_base;public:explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { }_Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); }__gnu_cxx::__aligned_buffer<_Tp> _M_storage;};public:using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;template<typename... _Args>_Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args): _M_impl(__a){ // _GLIBCXX_RESOLVE_LIB_DEFECTS// 2070. allocate_shared should use allocator_traits<A>::constructallocator_traits<_Alloc>::construct(__a, _M_ptr(),std::forward<_Args>(__args)...); // might throw}~_Sp_counted_ptr_inplace() noexcept { }virtual void_M_dispose() noexcept{ allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());}// Override because the allocator needs to know the dynamic typevirtual void_M_destroy() noexcept{ __allocator_type __a(_M_impl._M_alloc());__allocated_ptr<__allocator_type> __guard_ptr{ __a, this };this->~_Sp_counted_ptr_inplace();}// Sneaky trick so __shared_ptr can get the managed pointervirtual void*_M_get_deleter(const std::type_info& __ti) noexcept{ #if __cpp_rttiif (__ti == typeid(_Sp_make_shared_tag)) #elseif (&__ti == &_Sp_make_shared_tag::_S_ti()) #endifreturn const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());return nullptr;}private:_Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }_Impl _M_impl;};
-
可以看到,用的自定义构造器的析构器进行资源释放.
-
-
-
如何区分数组,原始指针,和数据为
void
类型-
源码
template<typename _Tp, _Lock_policy _Lp,bool = is_array<_Tp>::value, bool = is_void<_Tp>::value>class __shared_ptr_access{ public:using element_type = _Tp;element_type&operator*() const noexcept{ __glibcxx_assert(_M_get() != nullptr);return *_M_get();}element_type*operator->() const noexcept{ _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);return _M_get();}private:element_type*_M_get() const noexcept{ return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }};// Define operator-> for shared_ptr<cv void>.template<typename _Tp, _Lock_policy _Lp>class __shared_ptr_access<_Tp, _Lp, false, true>{ public:using element_type = _Tp;element_type*operator->() const noexcept{ auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get();_GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr);return __ptr;}};// Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>.template<typename _Tp, _Lock_policy _Lp>class __shared_ptr_access<_Tp, _Lp, true, false>{ public:using element_type = typename remove_extent<_Tp>::type;#if __cplusplus <= 201402L[[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]]element_type&operator*() const noexcept{ __glibcxx_assert(_M_get() != nullptr);return *_M_get();}[[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]]element_type*operator->() const noexcept{ _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);return _M_get();} #endifelement_type&operator[](ptrdiff_t __i) const{ __glibcxx_assert(_M_get() != nullptr);__glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);return _M_get()[__i];}private:element_type*_M_get() const noexcept{ return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }};
-
根据特例化,实现了不同的父类.
-
-
总结
-
父类不同,子类支持的指针行为也不同.
-
-
-
weak
计数-
源码
template<_Lock_policy _Lp>class __weak_count{ public:constexpr __weak_count() noexcept : _M_pi(nullptr){ }__weak_count(const __shared_count<_Lp>& __r) noexcept: _M_pi(__r._M_pi){ if (_M_pi != nullptr)_M_pi->_M_weak_add_ref();}__weak_count(const __weak_count& __r) noexcept: _M_pi(__r._M_pi){ if (_M_pi != nullptr)_M_pi->_M_weak_add_ref();}__weak_count(__weak_count&& __r) noexcept: _M_pi(__r._M_pi){ __r._M_pi = nullptr; }~__weak_count() noexcept{ if (_M_pi != nullptr)_M_pi->_M_weak_release();}__weak_count&operator=(const __shared_count<_Lp>& __r) noexcept{ _Sp_counted_base<_Lp>* __tmp = __r._M_pi;if (__tmp != nullptr)__tmp->_M_weak_add_ref();if (_M_pi != nullptr)_M_pi->_M_weak_release();_M_pi = __tmp;return *this;}__weak_count&operator=(const __weak_count& __r) noexcept{ _Sp_counted_base<_Lp>* __tmp = __r._M_pi;if (__tmp != nullptr)__tmp->_M_weak_add_ref();if (_M_pi != nullptr)_M_pi->_M_weak_release();_M_pi = __tmp;return *this;}__weak_count&operator=(__weak_count&& __r) noexcept{ if (_M_pi != nullptr)_M_pi->_M_weak_release();_M_pi = __r._M_pi;__r._M_pi = nullptr;return *this;}void_M_swap(__weak_count& __r) noexcept{ _Sp_counted_base<_Lp>* __tmp = __r._M_pi;__r._M_pi = _M_pi;_M_pi = __tmp;}long_M_get_use_count() const noexcept{ return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }bool_M_less(const __weak_count& __rhs) const noexcept{ return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }bool_M_less(const __shared_count<_Lp>& __rhs) const noexcept{ return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }// Friend function injected into enclosing namespace and found by ADLfriend inline booloperator==(const __weak_count& __a, const __weak_count& __b) noexcept{ return __a._M_pi == __b._M_pi; }private:friend class __shared_count<_Lp>;_Sp_counted_base<_Lp>* _M_pi;};
-
说明
-
采用
shared_count
类似的手段,而且weak_count
和shared_count
共享数据_Sp_counted_base<_Lp>* _M_pi;
. -
可以根据构造和析构查看,释放和创建的行为.
-
可以根据前面的
_Sp_counted_base
看到,weak
的释放是释放整个计数对象.
-
-
-
计数
-
引用计数
-
可以看到
__shared_count
的operator=
的拷贝构造.仅仅共享加一. -
weak
的+1
在weak
的计数上.
-
-
析构
-
只有
shared
为0
会释放. -
只有
weak
为0
的时候会释放计数对象.
-
-
-
总结
-
指针操作由
__shared_ptr_access
的特例化决定.以区分数组,指针和void
. -
元素的基本操作由
shared_ptr
的外层封装. -
__shared_count
和__shared_ptr
的成员变量 -
__weak_count
和__weak_ptr
的成员变量 -
__weak_count
和__shared_count
指向对象,但是分别控制_Sp_counted_base
的两个计数成员. -
引用计数由
_Sp_counted_base
来控制. -
引用计数的多线程安全由
_Sp_counted_base
的成员函数特例化实现来控制. -
析构的不同对待由
_Sp_counted_base
的子类和虚函数重载类控制.
-
详细解决方案
shared_ptr 源码分析
热度:4 发布时间:2023-12-22 02:43:20.0
相关解决方案
- C++基础知识 - shared_ptr 使用详解 (C++11)
- std::shared_ptr 作为参数传递的时候,到底应不应该用引用?
- shared_ptr 原理及事故
- C++智能指针:unique_ptr、shared_ptr、weak_ptr
- C++---智能指针(auto_ptr、unique_ptr、shared_ptr)
- ros kinetic版编译error: ‘shared_ptr’ in namespace ‘std’ does not name a template type
- shared_ptr 两种常见的使用方式 (1)
- auto_ptr与shared_ptr --- shared_ptr (2)
- shared_ptr 源码分析
- 智能指针:模拟实现auto_ptr,scoped_ptr,shared_ptr
- Boost库--功能介绍--boost::shared_ptr
- const与智能指针:const shared_ptr<T>&
- C++自定义智能指针——shared_ptr
- 5.2new、delete探秘,智能指针概述、shared_ptr
- error: ‘shared_ptr’ in namespace ‘std’ does not name a template type
- 问题解决:shared_ptr Assertion px != 0 failed 及debug经验分享