shared_ptr & weak_ptr 源码分析

15 篇文章 0 订阅

shared_ptr & weak_ptr

本次源码采用的是vs2015 c++11的源码进行分析

sizeof(shard_ptr<int>)=?

回答这个问题,就需要看shared_ptr 的数据结构,下边进行源码分析

shared_ptr

C++
template<class _Ty>
        class shared_ptr
                : public _Ptr_base<_Ty>
               

_Ptr_base<_Ty>

C++
template<class _Ty>
class _Ptr_base
{        // base class for shared_ptr and weak_ptr
public:
        typedef _Ptr_base<_Ty> _Myt;
        typedef _Ty element_type;
private:
        _Ty *_Ptr;
        _Ref_count_base *_Rep;
 }

也就是说 shared_ptr 内部数据就是两个指针_Ptr 与 _Rep

那就很好理解了,在32位字节上4字节对齐情况下是8个字节

在64位机器上,8字节对齐请下是16个字节

shared_ptr 引用计数为0的时候做了什么

shared_ptr::_Reset0

C++
template<class _Ty>
        class shared_ptr
                : public _Ptr_base<_Ty>
 {
                 void _Reset()
                {        // release resource
                    _Reset(0, 0);
                }

                template<class _Ty2>
                void _Reset(const _Ptr_base<_Ty2>& _Other)
                {        // release resource and take ownership of _Other._Ptr
                    _Reset(_Other._Ptr, _Other._Rep);
                }

                template<class _Ty2>
                void _Reset(const _Ptr_base<_Ty2>& _Other, bool _Throw)
                {        // release resource and take ownership from weak_ptr _Other._Ptr
                    _Reset(_Other._Ptr, _Other._Rep, _Throw);
                }
                    template<class _Ty2>
                    void _Reset(auto_ptr<_Ty2>&& _Other)
                    {        // release resource and take _Other.get()
                        _Ty2 *_Px = _Other.get();
                        _Reset0(_Px, new _Ref_count<_Ty>(_Px));
                        _Other.release();
                        _Enable_shared(_Px, _Rep);
                    }
                         void _Reset0(_Ty *_Other_ptr, _Ref_count_base *_Other_rep)
                        {        // release resource and take new resource
                            if (_Rep != 0)
                                    _Rep->_Decref();
                            _Rep = _Other_rep;
                            _Ptr = _Other_ptr;
                        }
                       
 }
 

_Ref_count_base::_Decref

C++
class _Ref_count_base
{
     // common code for reference counting
    _Atomic_counter_t _Uses;
    _Atomic_counter_t _Weaks;
    void _Decref()
    {        // decrement use count
            if (_MT_DECR(_Uses) == 0)
            {        // destroy managed resource, decrement weak reference count
                _Destroy();
                _Decwref();
            }
    }
    virtual void _Delete_this() = 0;
        virtual void _Destroy() _NOEXCEPT
        {        // destroy managed resource
            delete _Ptr;
        }
        void _Decwref()
        {        // decrement weak reference count
            if (_MT_DECR(_Weaks) == 0)
                _Delete_this();
        }
};

_Ref_count_del::_Delete_this

C++
template<class _Ty,
        class _Dx>
        class _Ref_count_del
        : public _Ref_count_base
        {        // handle reference counting for object with deleter
public:
        _Ref_count_del(_Ty *_Px, _Dx _Dt)
                : _Ref_count_base(), _Mypair(_One_then_variadic_args_t(), _Dt, _Px)
                {        // construct
                }

        virtual void *_Get_deleter(
                const _XSTD2 type_info& _Typeid) const _NOEXCEPT
                {        // return address of deleter object
                return ((void *)(_Typeid == typeid(_Dx)
                        ? _STD addressof(_Mypair._Get_first()) : 0));
                }

private:
        virtual void _Destroy() _NOEXCEPT
                {       
                // _Get_first 拿到的是自定义析构方法
                //_Mypair._Get_second() 管理的指针
                _Mypair._Get_first()(_Mypair._Get_second());
                }

        virtual void _Delete_this() _NOEXCEPT
                {        // destroy self
                delete this;
                }

        _Compressed_pair<_Dx, _Ty *> _Mypair;
        };

_Ref_count::_Delete_this

C++
template<class _Ty>
        class _Ref_count
        : public _Ref_count_base
        {        // handle reference counting for object without deleter
public:
        _Ref_count(_Ty *_Px)
                : _Ref_count_base(), _Ptr(_Px)
                {        // construct
                }

private:
        virtual void _Destroy() _NOEXCEPT
                {        // destroy managed resource
                delete _Ptr;
                }

        virtual void _Delete_this() _NOEXCEPT
                {        // destroy self
                delete this;
                }

        _Ty * _Ptr;
        };
 

当shared ptr 创时候带了自定义析构函数会使用_Ref_count_del这个类

默认使用的是_Delete_this

通过上边分析可以看出,当智能指针的引用计数清0的时候首先会销毁ptr,其次在判断弱引用的技术是否也清0了,如果清0了就一并释放了

weak_ptr 分析

weak_ptr构造

C++
template<class _Ty>
        class weak_ptr
                : public _Ptr_base<_Ty>
        {        // class for pointer to reference counted resource
public:
        typedef weak_ptr<_Ty> _Myt;
        typedef _Ptr_base<_Ty> _Mybase;

        constexpr weak_ptr() _NOEXCEPT
        {        // construct empty weak_ptr object
        }

        weak_ptr(const weak_ptr& _Other) _NOEXCEPT
        {        // construct weak_ptr object for resource pointed to by _Other
            this->_Resetw(_Other);
        }
        //is_convertible 会判断原weak_ptr持有的指针跟构造的指针是否同一个类型
        //如果是同一个类型使用下边方法,不是会调用其他的构造芳芳
        //这也就是SFINAE典型应用
        template<class _Ty2,
                class = typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,
                        void>::type>
        weak_ptr(const shared_ptr<_Ty2>& _Other) _NOEXCEPT
        {        // construct weak_ptr object for resource owned by _Other
            this->_Resetw(_Other);
        }  
  }

通过shared_ptr构造weak_ptr 过程

_Ptr_base::_Resetw

C++
template<class _Ty>
class _Ptr_base
{        // base class for shared_ptr and weak_ptr
    void _Resetw()
    {        // release weak reference to resource
        _Resetw((_Ty *)0, 0);
    }
       
   template<class _Ty2>
    void _Resetw(const _Ptr_base<_Ty2>& _Other)
    {        // release weak reference to resource and take _Other._Ptr
        _Resetw(_Other._Ptr, _Other._Rep);
    }
    template<class _Ty2>
    void _Resetw(_Ty2 *_Other_ptr, _Ref_count_base *_Other_rep)
    {        // point to _Other_ptr through _Other_rep
        if (_Other_rep)
                _Other_rep->_Incwref();
        if (_Rep != 0)
                _Rep->_Decwref();
        _Rep = _Other_rep;
        _Ptr = const_cast<remove_cv_t<_Ty2> *>(_Other_ptr);
    }
public:
        typedef _Ptr_base<_Ty> _Myt;
        typedef _Ty element_type;
private:
        _Ty *_Ptr;
        _Ref_count_base *_Rep;
       
 }

通过上边的_Resetw 可以发现 它是从shared_ptr中的_Ptr与_Rep 构建出来的,为了防止构建过程中出现野指针的情况,它以上来就会调用_Other_rep->_Incwref();增加一个引用计数

std::enable_shared_from_this

enable_shared_from_this 定义

C++
template<class _Ty>
        class enable_shared_from_this
        {        // provide member functions that create shared_ptr to this
public:
        typedef _Ty _EStype;

        shared_ptr<_Ty> shared_from_this()
                {        // return shared_ptr
                return (shared_ptr<_Ty>(_Wptr));
                }

        shared_ptr<const _Ty> shared_from_this() const
                {        // return shared_ptr
                return (shared_ptr<const _Ty>(_Wptr));
                }
 private:
   
        weak_ptr<_Ty> _Wptr;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值