shared_ptr 和weak_ptr

7 篇文章 0 订阅
4 篇文章 0 订阅
本文详细介绍了C++智能指针shared_ptr和weak_ptr的内部工作机制。shared_ptr通过引用计数管理内存,其核心是_Sp_counted_base类,而weak_ptr则用于不增加对象生命周期的弱引用,两者都涉及到_Sp_counted_base的引用计数管理和内存控制。在拷贝、赋值和析构过程中,引用计数会相应增减,确保资源的正确管理。
摘要由CSDN通过智能技术生成

shared_ptr

参考自https://www.jianshu.com/p/b6ac02d406a0

shared_ptr类几乎什么都没有做,它是继承了__shared_ptr, __shared_ptr内部有一个类型为__shared_count类型的成员_M_refcount, __shared_count内部有类型为_Sp_counted_base*的_M_pi的成员, _Sp_counted_base才是整个shared_ptr功能的核心,通过_Sp_counted_base控制引用计数来管理托管的内存,由图可见_Sp_counted_base内部不持有托管内存的指针,这里__shared_count内部的成员其实是一个继承自_Sp_counted_base的_Sp_counted_ptr类型,_Sp_counted_ptr类型内部持有托管内存的指针_M_ptr, _M_pi是一个_Sp_counted_base基类对象指针,指向_Sp_counted_ptr子类对象内存,这样_M_pi内部就既可以控制引用计数,又可以在最后释放托管内存。

这里称_M_pi为管理对象,它内部的_M_ptr为托管对象,管理同一块托管对象的多个shared_ptr内部共用一个管理对象(_M_pi), 这里的多个shared_ptr可能是通过第一个shared_ptr拷贝或者移动而来, 管理对象内部有两个成员变量_M_use_count和_M_weak_count, _M_use_count表示托管对象的引用计数,控制托管对象什么时候析构和释放,大概就是有N个shared_ptr的拷贝那引用计数就是N,当引用计数为0时调用托管对象的析构函数且释放内存。_M_weak_count表示管理对象的引用计数,管理对象也是一个内存指针,这块指针是初始化第一个shared_ptr时new出来的,到最后也需要delete,所以使用_M_weak_count来控制管理对象什么时候析构,我们平时用到的weak_ptr内部其实持有的就是这个管理对象的指针,当weak_ptr拷贝时,管理对象的引用计数_M_weak_count就会增加,当_M_weak_count为0时,管理对象_M_pi就会析构且释放内存。

class shared_ptr

template <typename _Tp> class shared_ptr : public __shared_ptr<_Tp>

成员函数

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

成员变量

_Tp *_M_ptr;                     // Contained pointer.
__shared_count<_Lp> _M_refcount; // Reference counter.

成员函数

   // 重载赋值运算符 
   __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;
    }


  // 构造函数
   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);
    }

	// 析构函数
    ~__shared_ptr() = default;

class __shared_count

成员变量

_Sp_counted_base<_Lp> *_M_pi;//_M_pi是一个_Sp_counted_base基类对象指针,指向_Sp_counted_ptr子类对象内存,这样_M_pi内部就既可以控制引用计数,又可以在最后释放托管内存。

成员函数

   // 构造函数
  template <typename _Ptr> explicit __shared_count(_Ptr __p) : _M_pi(0) {
      __try {
        _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p); //   _M_pi指向_Sp_counted_ptr子类对象内存
      }
      __catch(...) {
        delete __p;
        __throw_exception_again;
      }
    }

  // 析构函数
    ~__shared_count() noexcept {
      if (_M_pi != nullptr)
        _M_pi->_M_release();
    }
 


   // 重载赋值运算符
   __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>

成员变量

private:
  _Atomic_word _M_use_count;  // #shared
  _Atomic_word _M_weak_count; // #weak + (#shared != 0)

成员函数

 _Sp_counted_base() noexcept : _M_use_count(1), _M_weak_count(1) {}
//注意当shared_ptr拷贝或者移动时_M_weak_count是不会增加的,它表示的是管理对象的计数,只有当__M_use_count为0时_M_weak_count才会减1,除此之外_M_weak_count的数值是由weak_ptr控制的。

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>

成员变量

protected:
  _Ptr _M_ptr; // 托管内存的指针

成员函数

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

参考自https://www.jianshu.com/p/b6ac02d406a0

注意当shared_ptr拷贝或者移动时_M_weak_count是不会增加的,它表示的是管理对象的计数,只有当__M_use_count为0时_M_weak_count才会减1,除此之外_M_weak_count的数值是由weak_ptr控制的。

weak_ptr内部其实和shared_ptr内部持有的是同一个管理对象指针,即_Sp_counted_base的指针,当weak_ptr赋值、拷贝、析构时候,_Sp_counted_base内部的_M_weak_count会相应加减。当_M_weak_count为0时,表示不再需要管理对象来控制托管对象,调用_M_destroy()的delete this来释放管理对象内存。

weak_ptr不会延长原生指针所指向的对象的生命周期,实际上weak_ptr也没有原生指针的构造函数,只能由shared_ptr或weak_ptr进行构造。是一种不已延长生命周期为目的的只能指针。

class weak_ptr

template <typename _Tp> class weak_ptr : public __weak_ptr<_Tp>

成员函数

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) {}


// 用来延长生命周期
    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

成员变量

_Tp *_M_ptr;                   // Contained pointer.
__weak_count<_Lp> _M_refcount; // Reference counter.

成员函数

  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

成员变量

_Sp_counted_base<_Lp> *_M_pi;

成员函数

__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();
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海洋2416

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值