一、shared_ptr(_Yp* __p)
分析
#
1. 初始化
#
1// /usr/include/c++/12.2.0/bits/shared_ptr.h
2
3 template<typename _Tp>
4 class shared_ptr : public __shared_ptr<_Tp>
5 {
6 ...
7 public:
8 ...
9 /**
10 * @brief Construct a %shared_ptr that owns the pointer @a __p.
11 * @param __p A pointer that is convertible to element_type*.
12 * @post use_count() == 1 && get() == __p
13 * @throw std::bad_alloc, in which case @c delete @a __p is called.
14 */
15 template<typename _Yp, typename = _Constructible<_Yp*>>
16 explicit
17 shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
18 ...
19 }
1// /usr/include/c++/12.2.0/tr1/shared_ptr.h
2
3 // A smart pointer with reference-counted copy semantics. The
4 // object pointed to is deleted when the last shared_ptr pointing to
5 // it is destroyed or reset.
6 template<typename _Tp, _Lock_policy _Lp>
7 class __shared_ptr
8 {
9 public:
10
11 template<typename _Tp1>
12 explicit
13 __shared_ptr(_Tp1* __p)
14 : _M_ptr(__p), _M_refcount(__p)
15 {
16 __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
17 typedef int _IsComplete[sizeof(_Tp1)];
18 __enable_shared_from_this_helper(_M_refcount, __p, __p);
19 }
20 ...
21 _Tp* _M_ptr; // Contained pointer.
22 __shared_count<_Lp> _M_refcount; // Reference counter.
23 };
__shared_ptr
创建时创建了__shared_count
__shared_count
创建时,new
了一个_Sp_counted_ptr
1// /usr/include/c++/12.2.0/bits/shared_ptr_base.h
2 template<_Lock_policy _Lp>
3 class __shared_count
4 {
5 public:
6 ...
7 template<typename _Ptr>
8 explicit
9 __shared_count(_Ptr __p) : _M_pi(0)
10 {
11 __try
12 {
13 _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
14 }
15 __catch(...)
16 {
17 delete __p;
18 __throw_exception_again;
19 }
20 }
21 }
2. 析构
#
1std::_Sp_counted_ptr<testS*, (__gnu_cxx::_Lock_policy)2>::_M_dispose(std::_Sp_counted_ptr<testS*, (__gnu_cxx::_Lock_policy)2> * const this) (/usr/include/c++/12.2.0/bits/shared_ptr_base.h:428)
2std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release(std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2> * const this) (/usr/include/c++/12.2.0/bits/shared_ptr_base.h:346)
3std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count(std::__shared_count<(__gnu_cxx::_Lock_policy)2> * const this) (/usr/include/c++/12.2.0/bits/shared_ptr_base.h:1071)
4std::__shared_ptr<testS, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr(std::__shared_ptr<testS, (__gnu_cxx::_Lock_policy)2> * const this) (/usr/include/c++/12.2.0/bits/shared_ptr_base.h:1524)
5std::shared_ptr<testS>::~shared_ptr(std::shared_ptr<testS> * const this) (/usr/include/c++/12.2.0/bits/shared_ptr.h:175)
- 由于
__shared_count
是__shared_ptr
的成员变量,所以在释放__shared_ptr
的时候就会进行释放
1// /usr/include/c++/12.2.0/tr1/shared_ptr.h
2
3 template<_Lock_policy _Lp = __default_lock_policy>
4 class __shared_count
5 {
6 public:
7 ...
8 ~__shared_count() // nothrow
9 {
10 if (_M_pi != 0)
11 _M_pi->_M_release();
12 }
13 ...
14 private:
15 ...
16 _Sp_counted_base<_Lp>* _M_pi;
17 };
1// /usr/include/c++/12.2.0/bits/shared_ptr_base.h
2 template<>
3 inline void
4 _Sp_counted_base<_S_atomic>::_M_release() noexcept
5 {
6 ...
7 if (__atomic_load_n(__both_counts, __ATOMIC_ACQUIRE) == __unique_ref)
8 {
9 // Both counts are 1, so there are no weak references and
10 // we are releasing the last strong reference. No other
11 // threads can observe the effects of this _M_release()
12 // call (e.g. calling use_count()) without a data race.
13 _M_weak_count = _M_use_count = 0;
14 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
15 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
16 _M_dispose();
17 _M_destroy();
18 return;
19 }
20 ...
21 }
22 ...
23}
_M_dispose
,_Sp_counted_ptr
继承了_Sp_counted_base
,上面的_M_pi
实际上是使用了_Sp_counted_ptr
的方法
- 直接调用delete
1// /usr/include/c++/12.2.0/tr1/shared_ptr.h
2 // Counted ptr with no deleter or allocator support
3 template<typename _Ptr, _Lock_policy _Lp>
4 class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
5 {
6 public:
7 ...
8 virtual void
9 _M_dispose() noexcept
10 { delete _M_ptr; }
11 }
3. 使用构造函数的注意事项
#
3.1. 不能使用栈变量进行初始化
#
- 由于最终会调用delete,使用栈变量不能delete,会崩溃
1void func() {
2 testS a;
3 auto test = std::shared_ptr<testS>(&a); // 这样定义会崩溃
4}
3.2. 不能对同一个指针进行多次初始化
#
shared_ptr
从源码上看只是托管了堆上的指针的生命周期,并不会进行拷贝,如果使用多个shared_ptr
托管,会导致析构的时候多次delete
1void func() {
2 auto a = new testS();
3 auto test = std::shared_ptr<testS>(a);
4 auto test1 = std::shared_ptr<testS>(a); // 这里会造成重复delete
5}
二、shared_ptr(_Yp* __p, _Deleter __d)
#
1. 初始化
#
1std::_Sp_ebo_helper<0, main(int, char**)::<lambda(testS*)>, true>::_Sp_ebo_helper(struct {...} &&)(std::_Sp_ebo_helper<0, main(int, char**)::<lambda(testS*)>, true> * const this, struct {...} && __tp) (/usr/include/c++/12.2.0/bits/shared_ptr_base.h:471)
2std::_Sp_counted_deleter<testS*, main(int, char**)::<lambda(testS*)>, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_Impl::_Impl(testS *, struct {...}, const std::allocator<void> &)(std::_Sp_counted_deleter<testS*, main(int, char**)::<lambda(testS*)>, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_Impl * const this, testS * __p, struct {...} __d, const std::allocator<void> & __a) (/usr/include/c++/12.2.0/bits/shared_ptr_base.h:503)
3std::_Sp_counted_deleter<testS*, main(int, char**)::<lambda(testS*)>, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_deleter(testS *, struct {...}, const std::allocator<void> &)(std::_Sp_counted_deleter<testS*, main(int, char**)::<lambda(testS*)>, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> * const this, testS * __p, struct {...} __d, const std::allocator<void> & __a) (/usr/include/c++/12.2.0/bits/shared_ptr_base.h:521)
4std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<testS*, main(int, char**)::<lambda(testS*)>, std::allocator<void> >(testS *, struct {...}, std::allocator<void>)(std::__shared_count<(__gnu_cxx::_Lock_policy)2> * const this, testS * __p, struct {...} __d, std::allocator<void> __a) (/usr/include/c++/12.2.0/bits/shared_ptr_base.h:952)
5std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<testS*, main(int, char**)::<lambda(testS*)> >(testS *, struct {...})(std::__shared_count<(__gnu_cxx::_Lock_policy)2> * const this, testS * __p, struct {...} __d) (/usr/include/c++/12.2.0/bits/shared_ptr_base.h:939)
6std::__shared_ptr<testS, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<testS, main(int, char**)::<lambda(testS*)> >(testS *, struct {...})(std::__shared_ptr<testS, (__gnu_cxx::_Lock_policy)2> * const this, testS * __p, struct {...} __d) (/usr/include/c++/12.2.0/bits/shared_ptr_base.h:1478)
7std::shared_ptr<testS>::shared_ptr<testS, main(int, char**)::<lambda(testS*)> >(testS *, struct {...})(std::shared_ptr<testS> * const this, testS * __p, struct {...} __d) (/usr/include/c++/12.2.0/bits/shared_ptr.h:232)
1 /**
2 * @brief Construct a %shared_ptr that owns the pointer @a __p
3 * and the deleter @a __d.
4 * @param __p A pointer.
5 * @param __d A deleter.
6 * @post use_count() == 1 && get() == __p
7 * @throw std::bad_alloc, in which case @a __d(__p) is called.
8 *
9 * Requirements: _Deleter's copy constructor and destructor must
10 * not throw
11 *
12 * __shared_ptr will release __p by calling __d(__p)
13 */
14 template<typename _Yp, typename _Deleter,
15 typename = _Constructible<_Yp*, _Deleter>>
16 shared_ptr(_Yp* __p, _Deleter __d)
17 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
注意事项
#
1. 自定义delete必须删除传入的指针
#
- 最终析构会调用传入的delete函数,不会进行其他操作,所以需要在函数内自己调用delete或其他释放,不能只处理其他的逻辑
- 不调用delete就会存在内存泄漏
1auto test = std::shared_ptr<testS>(new testS(), [](testS* x) {
2 // 处理其他逻辑
3 if (x->temp) {
4 delete (uint64_t*)(x->temp);
5 x->temp = nullptr;
6 }
7 delete x; // 这一行必须
8});