c++11之std::shared_ptr剖析

一、概述

    c++11中std::shared_ptr<T>提供一种多个栈对象协作管理同一个堆对象的机制。以便在堆对象没有被引用的情况下将其free。         std::shared_ptr<T>的几个重要字段:
     _Ty *_Ptr;                                 //被管理的动态内存指针
     _Ref_count_base *_Rep;        //计数器基类指针,用于指示有几个shared_ptr共享_Ptr指向的对象,

                                                     //当其字段users减1为0时寓 意对象要被销毁

二、shared_ptr 相关类的数据组织结构:   

     类1.     // TEMPLATE CLASS _Ptr_base, shared_ptr的基类,构造函数实现字段的初始化。
        template<class _Ty>
            class _Ptr_base {
            public:

                //[0]
                constexpr _Ptr_base() _NOEXCEPT
                    : _Ptr(0), _Rep(0)
                    {    
                        // construct
                    }
            //重要字段
            private:
                _Ty *_Ptr;                                //被管理的动态内存指针
                _Ref_count_base *_Rep;        //计数器基类指针
        };

 

  类2  // TEMPLATE CLASS shared_ptr
    template<class _Ty>
    class shared_ptr : public _Ptr_base<_Ty> {
        public:

        typedef shared_ptr<_Ty> _Myt;

            template<class _Ux>
            explicit shared_ptr(_Ux *_Px)  // [1] 
            {    
                // construct shared_ptr object that owns _Px
                _Resetp(_Px);  //[2]
            }
            
            shared_ptr(const _Myt& _Other) _NOEXCEPT // [copy construct]
            {    
                // construct shared_ptr object that owns same resource as _Other
                this->_Reset(_Other);
            }
    }; 

 类3 .  //引用计数器基类,包含users、weaks……字段,引用计数等逻辑
        class _Ref_count_base {

            private:
                _Atomic_counter_t _Uses;    //引用计数
                _Atomic_counter_t _Weaks;   //weak计数

            protected:
                // construct,使用原子操作将引用计数与weak计数init为1【3】
                _Ref_count_base() {    
                    _Init_atomic_counter(_Uses, 1);
                    _Init_atomic_counter(_Weaks, 1);
                }
        };

   类4. 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:
            _Ty * _Ptr;         // 指向动态数据的指针
        };

三、构造一个shared_ptr对象的过程

                构造一个shared_ptr 对象开始
                        |
                        |
                       \|/                                                           |--------_Ptr(0)
                首先调用基类构造函数初始化字段为空    ---|
                        |                                                            |--------_Rep(0)
                        |
                       \|/
                在shared_ptr构造函数内调用_Resetp(_Px)    //_Px为new出的数据指针
                        |
                        |                                                                   1.创建计数器对象         |------上述[3]所示
                       \|/                                                                  |------------------------------|
               _Resetp0(_Px, new _Ref_count<_Ux>(_Px));----|                                    |------让计数器_Ptr指向数据内存
                |                                                                           | 2.
                |                                                                           |-------------------传入数据内存指针
                |       <传参数>
               \|/                                                                                       |----1. _Ptr = _Other_ptr;(新对象的_Ptr指针init)
        _Reset0(_Ty *_Other_ptr, _Ref_count_base *_Other_rep)----|
            (shared_ptr 字段初始化)                                                      |
                                                                                                         |----2. _Rep = _Other_rep;(计数器_Ref指针init)

 

三、拷贝构造shared_ptr
           copy构造一个shared_ptr 对象开始
        |
        |
       \|/                                                           |--------_Ptr(0)
首先调用基类构造函数初始化字段为空[0]---|
        |                                                            |--------_Rep(0)
        |
       \|/
this->_Reset(_Other)        //_Other为【被拷贝】shared_ptr对象
        |
        |                            
        |                                                  |--------【1】 递增被拷贝对象的引用计数
_Reset(_Other._Ptr, _Other._Rep)----|
                                                           |      //传参数
                                                           |-----_Reset0(_Other_ptr, _Other_rep);------- //(如果_Rep不为0递减计数器)
                                                                                                                         |
                                                                                                                         | //与被拷贝对象使用同一个引用计数器
                                                                                                                         |---【1】_Rep = _Other_rep
                                                                                                                         | //拷贝对象的数据指针段指向数据内存
                                                                                                                         |---【2】_Ptr = _Other_ptr

四、拷贝构造对象与被拷贝对象的内存状态

    

 

  

 

五、总结

   引用计数器是一个类类型,其中包含uses字段来记录当前引用动态对象的shared_ptr个数。一但uses-1为0动态对象

       将被销毁。

  实际每个shared_ptr对象共用一个“计数器”。因此在拷贝构造shared_ptr对象时,两者“都知道对方的存在”。

   shared_ptr类型拷贝构造对象,原对象以及引用计数对象都指向动态数据对象。

六、结束语

  现在对shared_ptr有一个较深层次的认识,以后文章将介绍原始指针与shared_ptr在使用上的一些问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值