auto_prt(源码学习)

来源:互联网 发布:抖音为什么网络不给力 编辑:程序博客网 时间:2024/06/05 22:33

转自:http://blog.csdn.net/rao_warrior/article/details/8295223

大家都知道,C++的auto_ptr auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理。然而对于auto_ptr来说,它的规则也挺难记,有时候,我也在想,为什么会有这些规则呢,

1) 两个auto_ptr不能同时拥有同一个对象
2) 我们不应该用auto_ptr来管理一个数组指针。
3) auto_ptr赋值运算,应该叫传值,传给别人,自己没有了。
4) auto_ptr的几种隐式转换
5) auto_ptr的几种运算符操作

我相信看看原码,大家都会明白了, 因为在源码面前,没有隐藏

  1. /*在.../VC/include/memory文件中*/  
  2.  #define _THROW0()  throw ()  
  3. template<class _Ty>  
  4. struct auto_ptr_ref  
  5. {   // proxy reference for auto_ptr copying  
  6.     explicit auto_ptr_ref(_Ty *_Right)  
  7.         : _Ref(_Right)  
  8.     {   // construct from generic pointer to auto_ptr ptr  
  9.     }  
  10.     _Ty *_Ref;  // generic pointer to auto_ptr ptr  
  11. };  
  12.   
  13.   
  14. template<class _Ty>  
  15. class auto_ptr  
  16. {   // wrap an object pointer to ensure destruction  
  17. public:  
  18.     typedef _Ty element_type;  
  19.   
  20.     explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()  
  21.         : _Myptr(_Ptr)  
  22.     {   // construct from object pointer  
  23.     }  
  24.   
  25.     auto_ptr(auto_ptr<_Ty>& _Right) _THROW0()  
  26.         : _Myptr(_Right.release())  
  27.     {   // construct by assuming pointer from _Right auto_ptr  
  28.     }  
  29.   
  30.     auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()  
  31.     {   // construct by assuming pointer from _Right auto_ptr_ref  
  32.         _Ty *_Ptr = _Right._Ref;  
  33.         _Right._Ref = 0;    // release old  
  34.         _Myptr = _Ptr;  // reset this  
  35.     }  
  36.     /*auto_ptr<_Other>强制转换*/  
  37.     template<class _Other>  
  38.     operator auto_ptr<_Other>() _THROW0()  
  39.     {   // convert to compatible auto_ptr  
  40.         return (auto_ptr<_Other>(*this));/*调用拷贝构造函数,返回该对象的引用*/  
  41.     }  
  42.     /*auto_ptr_ref<_Other>强制转换*/  
  43.     template<class _Other>  
  44.     operator auto_ptr_ref<_Other>() _THROW0()  
  45.     {   // convert to compatible auto_ptr_ref  
  46.         _Other *_Cvtptr = _Myptr;   // test implicit conversion  
  47.         auto_ptr_ref<_Other> _Ans(_Cvtptr);  
  48.         _Myptr = 0; // pass ownership to auto_ptr_ref  
  49.         return (_Ans);  
  50.     }  
  51.   
  52.     /*重载运算符“=”*/  
  53.     template<class _Other>  
  54.     auto_ptr<_Ty>& operator=(auto_ptr<_Other>& _Right) _THROW0()  
  55.     {   // assign compatible _Right (assume pointer)  
  56.         reset(_Right.release());  
  57.         return (*this);  
  58.     }  
  59.     /*拷贝构造函数*/  
  60.     template<class _Other>  
  61.     auto_ptr(auto_ptr<_Other>& _Right) _THROW0()  
  62.         : _Myptr(_Right.release())  
  63.     {   // construct by assuming pointer from _Right  
  64.     }  
  65.   
  66.     auto_ptr<_Ty>& operator=(auto_ptr<_Ty>& _Right) _THROW0()  
  67.     {   // assign compatible _Right (assume pointer)  
  68.         reset(_Right.release());  
  69.         return (*this);  
  70.     }  
  71.   
  72.     auto_ptr<_Ty>& operator=(auto_ptr_ref<_Ty> _Right) _THROW0()  
  73.     {   // assign compatible _Right._Ref (assume pointer)  
  74.         _Ty *_Ptr = _Right._Ref;  
  75.         _Right._Ref = 0;    // release old  
  76.         reset(_Ptr);    // set new  
  77.         return (*this);  
  78.     }  
  79.   
  80.     ~auto_ptr()  
  81.     {   // destroy the object  
  82.         if (_Myptr != 0)  
  83.             delete _Myptr;  
  84.     }  
  85.     /*重载"*"运算符*/  
  86.     _Ty& operator*() const _THROW0()  
  87.     {   // return designated value  
  88.   
  89. #if _HAS_ITERATOR_DEBUGGING  
  90.         if (_Myptr == 0)  
  91.             _DEBUG_ERROR("auto_ptr not dereferencable");  
  92. #endif /* _HAS_ITERATOR_DEBUGGING */  
  93.         __analysis_assume(_Myptr);  
  94.         return (*get()); //调用get取_Myptr所指向的数据,相当于*_Myptr  
  95.     }  
  96.     /*重载"->"运算符*/  
  97.     _Ty *operator->() const _THROW0()  
  98.     {   // return pointer to class object  
  99.   
  100. #if _HAS_ITERATOR_DEBUGGING  
  101.         if (_Myptr == 0)  
  102.             _DEBUG_ERROR("auto_ptr not dereferencable");  
  103. #endif /* _HAS_ITERATOR_DEBUGGING */  
  104.   
  105.         return (get());//调用get取_Myptr,相当于_Myptr  
  106.     }  
  107.   
  108.     _Ty *get() const _THROW0()  
  109.     {   // return wrapped pointer  
  110.         return (_Myptr);  
  111.     }  
  112.     /*将_Myptr设为0,并返回需要释放的数据*/  
  113.     _Ty *release() _THROW0()  
  114.     {   // return wrapped pointer and give up ownership  
  115.         _Ty *_Tmp = _Myptr;  
  116.         _Myptr = 0;  
  117.         return (_Tmp);  
  118.     }  
  119.     /*将_Myptr原来内存释放,重置为_Ptr*/  
  120.     void reset(_Ty* _Ptr = 0)  
  121.     {   // destroy designated object and store new pointer  
  122.         if (_Ptr != _Myptr && _Myptr != 0)  
  123.             delete _Myptr;  
  124.         _Myptr = _Ptr;  
  125.     }  
  126.   
  127. private:  
  128.     _Ty *_Myptr;    // the wrapped object pointer  
  129. };  

1)两个auto_ptr不能同时拥有同一个对象

  1. ~auto_ptr()  
  2. {   // destroy the object  
  3.     if (_Myptr != 0)  
  4.         delete _Myptr;  
  5. }  

上面的代码已经能够说明问题了,如果一个对象,两个auto_ptr则会delete 两次,必须出错
2) 我们不应该用auto_ptr来管理一个数组指针。
看看  _Ty *release() _THROW0() ,这个里面都是delete,没有delete []

3) auto_ptr赋值运算,应该叫传值,传给别人,自己没有了。

  1. /*重载运算符“=”*/  
  2. template<class _Other>  
  3. auto_ptr<_Ty>& operator=(auto_ptr<_Other>& _Right) _THROW0()  
  4. {   // assign compatible _Right (assume pointer)  
  5.     reset(_Right.release());  
  6.     return (*this);  
  7. }  
看了上面的"="就全明白了,在赋值给别人的时候,自己也释放了

4) auto_ptr的几种隐式转换
operator auto_ptr<_Other>() _THROW0()
operator auto_ptr_ref<_Other>() _THROW0()

那么可以看到做了 auto_ptr<_Other> 、auto_ptr_ref<_Other>的强制转换

5) auto_ptr的几种运算符操作

这个在代码里面很显然啦,里面部分都有注释哈


原创粉丝点击