`
rocky2com
  • 浏览: 38594 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

auto_ptr 源码

 
阅读更多

最近开了auto_ptr,看了它的很多的应用与规则,有些迷惑的地方,故拿来它的源码研究一翻:

Code:
  1. template<typename_Tp1>
  2. structauto_ptr_ref
  3. {
  4. _Tp1*_M_ptr;
  5. explicit
  6. auto_ptr_ref(_Tp1*__p):_M_ptr(__p){}
  7. };
  8. template<typename_Tp>
  9. classauto_ptr
  10. {
  11. private:
  12. _Tp*_M_ptr;
  13. public:
  14. ///Thepointed-totype.
  15. typedef_Tpelement_type;
  16. explicit
  17. auto_ptr(element_type*__p=0)throw():_M_ptr(__p){}
  18. auto_ptr(auto_ptr&__a)throw():_M_ptr(__a.release()){}
  19. template<typename_Tp1>
  20. auto_ptr(auto_ptr<_Tp1>&__a)throw():_M_ptr(__a.release()){}
  21. auto_ptr&
  22. operator=(auto_ptr&__a)throw()
  23. {
  24. reset(__a.release());
  25. return*this;
  26. }
  27. template<typename_Tp1>
  28. auto_ptr&
  29. operator=(auto_ptr<_Tp1>&__a)throw()
  30. {
  31. reset(__a.release());
  32. return*this;
  33. }
  34. ~auto_ptr(){delete_M_ptr;}
  35. element_type&
  36. operator*()constthrow()
  37. {
  38. _GLIBCXX_DEBUG_ASSERT(_M_ptr!=0);
  39. return*_M_ptr;
  40. }
  41. element_type*
  42. operator->()constthrow()
  43. {
  44. _GLIBCXX_DEBUG_ASSERT(_M_ptr!=0);
  45. return_M_ptr;
  46. }
  47. element_type*
  48. get()constthrow(){return_M_ptr;}
  49. element_type*
  50. release()throw()
  51. {
  52. element_type*__tmp=_M_ptr;
  53. _M_ptr=0;
  54. return__tmp;
  55. }
  56. void
  57. reset(element_type*__p=0)throw()
  58. {
  59. if(__p!=_M_ptr)
  60. {
  61. delete_M_ptr;
  62. _M_ptr=__p;
  63. }
  64. }
  65. auto_ptr(auto_ptr_ref<element_type>__ref)throw()
  66. :_M_ptr(__ref._M_ptr){}
  67. auto_ptr&
  68. operator=(auto_ptr_ref<element_type>__ref)throw()
  69. {
  70. if(__ref._M_ptr!=this->get())
  71. {
  72. delete_M_ptr;
  73. _M_ptr=__ref._M_ptr;
  74. }
  75. return*this;
  76. }
  77. template<typename_Tp1>
  78. operatorauto_ptr_ref<_Tp1>()throw()
  79. {returnauto_ptr_ref<_Tp1>(this->release());}
  80. template<typename_Tp1>
  81. operatorauto_ptr<_Tp1>()throw()
  82. {returnauto_ptr<_Tp1>(this->release());}
  83. };

1 首先看一下开始的哪个小结构体

Code:
  1. template<typename_Tp1>
  2. structauto_ptr_ref
  3. {
  4. _Tp1*_M_ptr;
  5. explicit
  6. auto_ptr_ref(_Tp1*__p):_M_ptr(__p){}
  7. };

这个结构体成员中仅有一个指针和一个显示构造函数。仅从表面上来看,它封装了一个指针类型,从源码来看,它提供了一种转换,即:从这种结构体类型到auto_ptr的转换。

2 类型定义

Code:
  1. typedef_Tpelement_type;

为auto_ptr定一个成员类型。我们可以如下方法使用这种类型:

Code:
  1. #include<iostream>
  2. #include<memory>
  3. #include<typeinfo>
  4. #include<string>
  5. usingnamespacestd;
  6. intmain()
  7. {
  8. auto_ptr<int>::element_typep=6;
  9. cout<<p<<endl;
  10. cout<<typeid(p).name()<<endl;
  11. system("pause");
  12. return0;
  13. }

在程序中auto_ptr<int>::element_type 其实就是int类型。我们在程序中也验证了。

3 构造函数

Code:
  1. explicit
  2. auto_ptr(element_type*__p=0)throw():_M_ptr(__p){}

构造函数被定义为explicit,那么我们在定义对象的时候的存在隐式转换的定义就无法通过编译了。如:

Code:
  1. auto_ptr<int>p=newint(6);//error
  2. auto_ptr<int>p(newint(6));//ok;

4 拷贝构造函数

Code:
  1. auto_ptr(auto_ptr&__a)throw():_M_ptr(__a.release()){}
  2. template<typename_Tp1>
  3. auto_ptr(auto_ptr<_Tp1>&__a)throw():_M_ptr(__a.release()){}

拷贝构造函数被定义了两个版本,一个模板版本,一个非模板版本。为什么这样做呢?这不禁令我想起了模板的一个性质,即,当一个函数同时存在模板版本和非模板版本的时候,在函数进行调用的时候,编译器首先拿实参和非模板版本来进行比较,如果匹配就优先调用非模板版本。而不去再实例化一个版本。只有类型和非模板版本的参数类型不完全匹配或是不匹配的时候才去实例化一个新版本。

这里提供一个模板版本的目的是为了能够允许类型自动转换从而构造处合适的auto_ptr。例如:可以根据一个派生类对象构造出一个基类对像的auto_ptr。

4 赋值函数

Code:
  1. auto_ptr&
  2. operator=(auto_ptr&__a)throw()
  3. {
  4. reset(__a.release());
  5. return*this;
  6. }
  7. template<typename_Tp1>
  8. auto_ptr&
  9. operator=(auto_ptr<_Tp1>&__a)throw()
  10. {
  11. reset(__a.release());
  12. return*this;
  13. }

这个函数同样也有两个版本,其意义和拷贝构造函数的相同。由于构造函数被声明成为explicit。故这样的行为也无法通过编译:

Code:
  1. auto_ptr<int>p(newint(5));
  2. auto_ptr<int>q;
  3. q=p;//ok.
  4. q=newint(6);//error
  5. q=auto_ptr<int>(newint(6));//ok;

5 析构函数

Code:
  1. ~auto_ptr(){delete_M_ptr;}

析构函数简单,仅仅释放空间就ok了。

6 操作符重载

Code:
  1. element_type&
  2. operator*()constthrow()
  3. {
  4. _GLIBCXX_DEBUG_ASSERT(_M_ptr!=0);
  5. return*_M_ptr;
  6. }
  7. element_type*
  8. operator->()constthrow()
  9. {
  10. _GLIBCXX_DEBUG_ASSERT(_M_ptr!=0);
  11. return_M_ptr;
  12. }

这里重载了两个操作符,一个‘*’ 一个‘->’。这里面使用了断言。我猜测它_GLIBCXX_DEBUG_ASSERT就是assert。其实这样个函数的目的一个是为了得到指针所指的内容,一个是得到指针。

7 三个小函数

Code:
  1. element_type*
  2. get()constthrow(){return_M_ptr;}
  3. element_type*
  4. release()throw()
  5. {
  6. element_type*__tmp=_M_ptr;
  7. _M_ptr=0;
  8. return__tmp;
  9. }
  10. void
  11. reset(element_type*__p=0)throw()
  12. {
  13. if(__p!=_M_ptr)
  14. {
  15. delete_M_ptr;
  16. _M_ptr=__p;
  17. }
  18. }

get()函数就是为了获得封装的指针。release()函数其实也是一个封装操作,他这里干了两件事,一个是返回对象封装的指针,然后把该指针赋0.它的目的是释放现在的指针,令它指向0,并传递指针的地址。reset()函数是用来设置指针。首先判断当前指针是否有值,若有值释放之,并赋值新值。

8 和auto_ptr_ref有关的函数

Code:
  1. auto_ptr(auto_ptr_ref<element_type>__ref)throw()
  2. :_M_ptr(__ref._M_ptr){}
  3. auto_ptr&
  4. operator=(auto_ptr_ref<element_type>__ref)throw()
  5. {
  6. if(__ref._M_ptr!=this->get())
  7. {
  8. delete_M_ptr;
  9. _M_ptr=__ref._M_ptr;
  10. }
  11. return*this;
  12. }
  13. template<typename_Tp1>
  14. operatorauto_ptr_ref<_Tp1>()throw()
  15. {returnauto_ptr_ref<_Tp1>(this->release());}
  16. template<typename_Tp1>
  17. operatorauto_ptr<_Tp1>()throw()
  18. {returnauto_ptr<_Tp1>(this->release());}

首先是一个构造函数,然后是赋值函数,然后便是类型转换符。

构造函数和赋值函数提供了auto_ptr_ref类型到auto_ptr类型的转换。两个转换函数同样提供了auto_ptr_ref和auto_ptr之间的相互转换。

至此整个auto_ptr的源码就看完了,但是更多的东西还需在使用中才能有更深的体会。。

现在我们看auto_ptr的使用例子:

拥有权的转移

Code:
  1. #include<iostream>
  2. #include<memory>
  3. usingnamespacestd;
  4. template<typenameT>
  5. ostream&operator<<(ostream&strm,constauto_ptr<T>&p)
  6. {
  7. if(p.get()==NULL)
  8. {
  9. strm<<"NULL";
  10. }
  11. else
  12. {
  13. strm<<*p;
  14. }
  15. returnstrm;
  16. }
  17. intmain()
  18. {
  19. auto_ptr<int>p(newint(42));
  20. auto_ptr<int>q;
  21. cout<<"afterinitialization:"<<endl;
  22. cout<<"p:"<<p<<endl;
  23. cout<<"q:"<<q<<endl;
  24. q=p;
  25. cout<<"afterassigningautopointers:"<<endl;
  26. cout<<"p:"<<p<<endl;
  27. cout<<"q:"<<q<<endl;
  28. *q+=13;
  29. p=q;
  30. cout<<"afterchangeandreassignment:"<<endl;
  31. cout<<"p:"<<p<<endl;
  32. cout<<"q:"<<q<<endl;
  33. system("pause");
  34. return0;
  35. }

const auto_ptr<T> 拥有权不能转移,但可以改变它的值。

Code:
  1. #include<iostream>
  2. #include<memory>
  3. usingnamespacestd;
  4. template<typenameT>
  5. ostream&operator<<(ostream&strm,constauto_ptr<T>&p)
  6. {
  7. if(p.get()==NULL)
  8. {
  9. strm<<"NULL";
  10. }
  11. else
  12. {
  13. strm<<*p;
  14. }
  15. returnstrm;
  16. }
  17. intmain()
  18. {
  19. auto_ptr<int>p(newint(42));
  20. constauto_ptr<int>t(newint(5));
  21. cout<<t<<endl;
  22. *t=6;//ok.
  23. cout<<t<<endl;
  24. p=t;///error.
  25. system("pause");
  26. return0;
  27. }
分享到:
评论

相关推荐

    C++ auto_ptr源码

    该文档是C++ auto_ptr源码,感兴趣的可以自行下载学习。

    unique_ptr源码

    该文档是C++ auto_ptr源码,感兴趣的可以自行下载学习,方便大家学习参考。

    C++智能指针:auto-ptr详解.pdf

    C++智能指针:auto_ptr详解 指针,相信⼤家并不陌⽣。⽆论是我们在进⾏查看内存还是在修改字符串,我们都会⽤到指针。 最常见的情况则是我们使⽤malloc或者new申请到了⼀块内存,然后⽤⼀个指针来保存起来。我们都...

    uboott移植实验手册及技术文档

    (2)进入 U-Boot源码目录 #cd u-boot-1.3.1 (3)创建自己的开发板: #cd board #cp smdk2410 fs2410 –a #cd fs2410 #mv smdk2410.c fs2410.c #vi Makefile (将 smdk2410修改为 fs2410) #cd ../../...

    Linux 内核里的“智能指针”

    现代的C/C++类库一般会提供智能指针来作为内存管理的折中方案,比如STL的auto_ptr,Boost的Smart_ptr库,QT的QPointer家族,甚至是基于C语言构建的GTK+也通过引用计数来实现类似的功能。Linux内核是如何解决这个问题...

    基于C、C++和ffmpeg编写的trt_yolov8推理模块源码+使用说明(拉流解码输入、支持cuda硬件解码).zip

    基于C、C++和ffmpeg编写的trt_yolov8推理模块源码+使用说明(拉流解码输入、支持cuda硬件解码).zip 先创建一个trt_infer实例 ~~~c++ std::string model_path = "/root/trt_projects/infer-main/workspace/yolov8n....

    LuaBind 源码 (Lua增强库)

    库要不就添加其所有源码到你的工程里面.你必须确保LuaBind目录在你的编译器包含目录中. LuaBind需要Boost 1.32.0 或者 1.33.0 (只需要头文件即可). LuaBind还需要Lua. 官方的构建LuaBind的方式是通过 Boost.Build ...

    log4cplus 源码(C++编写的开源的日志系统)

    std::auto_ptr _layout(new PatternLayout(pattern)); /* step 3: Attach the layout object to the appender */ _append-&gt;setLayout( _layout ); /* step 4: Instantiate a logger object */ Logger _...

    vld(Visual Leak Detector 内存泄露检测工具 源码)

     DWORD_PTR VisualLeakDetector::getprogramcounterx86x64 ()  {  DWORD_PTR programcounter;  __asm mov AXREG, [BPREG + SIZEOFPTR] // Get the return address out of the current stack frame  __asm mov ...

    《C++编程艺术》教程+代码

    2.3.8 关于auto_ptr 11 2.4 一个简单的C++垃圾回收器 11 2.5 详细讨论GCPtr 23 2.5.1 GCPtr的数据成员 23 2.5.2 函数findPtrInfo() 24 2.5.3 GCIterator typedef 25 2.5.4 GCPtr的构造函数 25 2.5.5 GCPtr的析构函数...

Global site tag (gtag.js) - Google Analytics