智能指针auto_ptr介绍
????? 我們大家都知道,new一定要和delete配合使用,但是有一種情況可能會使這種配對失效,如下程序:
#include <iostream> using namespace std; class normal_pointer_example { public:normal_pointer_example(){cout<<"構造函數執行!\n";}~normal_pointer_example(){cout<<"析構函數執行!\n";} }; class normal_pointer_wrong{};//normal_pointer_wrong異常 bool quit; void quit_func() {if(quit==true)cout<<"調用quit_func函數!\n";throw normal_pointer_wrong(); } int main() {try{normal_pointer_example *Npointer=new normal_pointer_example;quit=true;quit_func();delete Npointer;}catch (normal_pointer_wrong){cout<<"輸出normal_pointer_wrong異常!!\n";}return 0; }該程序的輸出結果為:
????? 注意上面這個輸出,我們看到當程序全部執行完了都沒有能夠調用析構函數將對象析構掉!這就說明并沒有把對象delete掉!!這個就是問題,因為這樣就有可能產生不易察覺的內存泄露。
????? 針對上面這個情況,我們就要使用智能指針類auto_ptr來避免這種情況出現。們來看一個auto_ptr類的聲明:
1 template<class _Ty>2 class auto_ptr
3 { // wrap an object pointer to ensure destruction
4 public:
5 typedef _Ty element_type;
6
7 explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()
8 : _Myptr(_Ptr)
9 { // construct from object pointer
10 }
11
12 auto_ptr(auto_ptr<_Ty>& _Right) _THROW0()
13 : _Myptr(_Right.release())
14 { // construct by assuming pointer from _Right auto_ptr
15 }
16
17 auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()
18 { // construct by assuming pointer from _Right auto_ptr_ref
19 _Ty *_Ptr = _Right._Ref;
20 _Right._Ref = 0; // release old
21 _Myptr = _Ptr; // reset this
22 }
23
24 template<class _Other>
25 operator auto_ptr<_Other>() _THROW0()
26 { // convert to compatible auto_ptr
27 return (auto_ptr<_Other>(*this));
28 }
29
30 template<class _Other>
31 operator auto_ptr_ref<_Other>() _THROW0()
32 { // convert to compatible auto_ptr_ref
33 _Other *_Cvtptr = _Myptr; // test implicit conversion
34 auto_ptr_ref<_Other> _Ans(_Cvtptr);
35 _Myptr = 0; // pass ownership to auto_ptr_ref
36 return (_Ans);
37 }
38
39
40 template<class _Other>
41 auto_ptr<_Ty>& operator=(auto_ptr<_Other>& _Right) _THROW0()
42 { // assign compatible _Right (assume pointer)
43 reset(_Right.release());
44 return (*this);
45 }
46
47 template<class _Other>
48 auto_ptr(auto_ptr<_Other>& _Right) _THROW0()
49 : _Myptr(_Right.release())
50 { // construct by assuming pointer from _Right
51 }
52
53 auto_ptr<_Ty>& operator=(auto_ptr<_Ty>& _Right) _THROW0()
54 { // assign compatible _Right (assume pointer)
55 reset(_Right.release());
56 return (*this);
57 }
58
59 auto_ptr<_Ty>& operator=(auto_ptr_ref<_Ty> _Right) _THROW0()
60 { // assign compatible _Right._Ref (assume pointer)
61 _Ty *_Ptr = _Right._Ref;
62 _Right._Ref = 0; // release old
63 reset(_Ptr); // set new
64 return (*this);
65 }
66
67 ~auto_ptr()
68 { // destroy the object
69 delete _Myptr;
70 }
71
72 _Ty& operator*() const _THROW0()
73 { // return designated value
74
75 #if _HAS_ITERATOR_DEBUGGING
76 if (_Myptr == 0)
77 _DEBUG_ERROR("auto_ptr not dereferencable");
78 #endif /* _HAS_ITERATOR_DEBUGGING */
79
80 __analysis_assume(_Myptr);
81
82 return (*get());
83 }
84
85 _Ty *operator->() const _THROW0()
86 { // return pointer to class object
87
88 #if _HAS_ITERATOR_DEBUGGING
89 if (_Myptr == 0)
90 _DEBUG_ERROR("auto_ptr not dereferencable");
91 #endif /* _HAS_ITERATOR_DEBUGGING */
92
93 return (get());
94 }
95
96 _Ty *get() const _THROW0()
97 { // return wrapped pointer
98 return (_Myptr);
99 }
100
101 _Ty *release() _THROW0()
102 { // return wrapped pointer and give up ownership
103 _Ty *_Tmp = _Myptr;
104 _Myptr = 0;
105 return (_Tmp);
106 }
107
108 void reset(_Ty* _Ptr = 0)
109 { // destroy designated object and store new pointer
110 if (_Ptr != _Myptr)
111 delete _Myptr;
112 _Myptr = _Ptr;
113 }
114
115 private:
116 _Ty *_Myptr; // the wrapped object pointer
117 };
118 _STD_END
????? 從上面這個定義就可以看出來,定義個智能指針就相當于創建了一個auto_ptr類的對象。現在我們再來看看這個類的析構函數:
~auto_ptr() { // destroy the objectdelete _Myptr; }????? 這里我們就可以看到,由于在私有數據成員中定義了一個模板指針:
_Ty *_Myptr;????? 所以說在上面的析構函數里面,當我們刪除_Myptr指針的時候,其實就是調用delete刪除_Myptr所指向的內存塊。所以每當我們定義一個智能指針,就是定義了一個auto_ptr類的對象,如:
auto_ptr<string> p (new string);????? 這句話就定義了一個auto_ptr類的對象p,尖括號里面的string用了初始化它的模板成員_Ty的類型。那么這里面,只要auto_ptr對象存在,它指向的字符串就存在,同理,如果auto_ptr對象不存在,會利用auto_ptr類中的析構函數自動銷毀它所指向的字符串,也就避免了內存泄露。
????? 好了,下面我們來用智能指針重寫上面的程序,看看會有什么結果。
#include <iostream> #include <memory> using namespace std; class normal_pointer_example { public:normal_pointer_example(){cout<<"構造函數執行!\n";}~normal_pointer_example(){cout<<"析構函數執行!\n";} }; class normal_pointer_wrong{};//normal_pointer_wrong異常 bool quit; void quit_func() {if(quit==true)cout<<"調用quit_func函數!\n";throw normal_pointer_wrong(); } int main() {try{auto_ptr<normal_pointer_example> Apointer (new normal_pointer_example);quit=true;quit_func();//delete Npointer;}catch (normal_pointer_wrong){cout<<"輸出normal_pointer_wrong異常!!\n";}return 0; }首先需要注意的是,要調用auto_ptr智能指針,必須包含頭文件<memory>。另外,程序的輸出:
????? 看到沒有,這樣一來,析構函數就執行咯~~
轉載于:https://www.cnblogs.com/uniqueliu/archive/2011/08/16/2141383.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的智能指针auto_ptr介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flex前端与Java服务端交互,反射机
- 下一篇: 使用ORACLE生成文本文件