以前寫過一篇關於智能指標的文章,但是還是沒有搞清楚兩個東西:
1。智能指標如何調用被智能指標指向的對象的成員函數,我不知道如何只通過智能指標去訪問指向對象的成員方法,請看我的寫的智能指標的demo。
#include <iostream>using namespace std; class A{private: int n;public: A(int m):n(m) {} ~A(){ cout<<"~A() is called\n"; } int get() const{ cout<<"get() is called\n"; }}; class SmartPtr //A的資源管理類,即智能指標類{private: A* a; public: B(A* b):a(b){ } ~B(){ delete a; //在SmartPtr中釋放A所佔的記憶體 cout<<"~B() is called\n"; } A* get() const{ return a; } //好挫的方法通過返回被管理對象的指標來調用它的成員方法}; int main(void){ SmartPtr b(new A(8)); A* a = b.get(); //不需要寫delete(a),也不要寫delete b int n = a->get(); cout<<n<<endl; return 0;}
從上看出,我是通過在智能指標類中返回A的指標,然後還是通過指向A的指標來訪問A中的方法,好挫。那麼有什麼更好的方法嗎?有,重載->操作符即可。雖然我不知道重載->操作符為什麼可以,但是確實給人感覺智能指標就是原指標。代碼如下:
#include <iostream>using namespace std;class Test{private: int n;public: Test(int m):n(m){} ~Test(){cout<<"~Test() is called\n";} void get() { cout<<"get() is called\n"; }};class SmartPtr{private: Test* n;public: SmartPtr(Test* m):n(m){} ~SmartPtr(){ cout<<"~SmartPtr is called\n"; delete n; n = NULL;} Test* operator->() const //重載->操作符,通過SmartPtr調用Test類中方法猶如調用直接調用一般 { return n; }};int main(){ {
SmartPtr ptr(new Test(10)); ptr->get(); //通過智能指標直接調用
}return 0;}
執行結果如下:
2。我想大家都認為智能指標,肯定是一個指標,就像int* ptr,ptr就是一個指標,而int ptr,而ptr就是一個非指標,其實智能指標非指標,它就如int ptr一樣,下面讓我來解釋一下為什麼吧?
首先我想說一下智能指標的原理,智能指標指向的對象不需要我們去delete,我們也不需要去delete智能指標,因為智能指標本身其實一個類,而類有new和非new進行建立對象,假設有一個智能指標類class SmartPtr,我們要這樣去建立一個智能指標的對象:SmartPtr ptr(new Test()),而不是SmartPtr* ptr = new SmartPtr( ( new Test() ) ),為什麼呢?因為智能指標是為了利用棧的對象在過程結束後自動調用解構函式的原理,SmartPtr ptr(new Test())是將ptr對象放在棧中,所以在任何一個過程結束後,自動調用SmartPtr的解構函式,只要我們在SmartPtr類中的解構函式去調用Test類的解構函式即可,而SmartPtr* ptr = new SmartPtr( ( new Test() ) )這種方法,過程結束後,ptr不會去自動調用SmartPtr的解構函式,需要我們程式員自己去delete,那麼智能指標的意義就不複存在。
下面是一個使用SmartPtr* ptr = new SmartPtr( ( new Test() ) )這種方法去建立一個智能指標對象,我們可以上面的代碼和圖進行比較,
#include <iostream>using namespace std;class Test{private: int n;public: Test(int m):n(m){} ~Test(){cout<<"~Test() is called\n";} void get() { cout<<"get() is called\n"; }};class SmartPtr{private: Test* n;public: SmartPtr(Test* m):n(m){} ~SmartPtr(){ cout<<"~SmartPtr is called\n"; delete n; n = NULL;} Test* operator->() const { return n; }};int main(){ { SmartPtr* ptr = new SmartPtr((new Test(10))); //此時退出過程時,將不再自動調用解構函式 } return 0;}
運行如下:
對於編譯器來說,智能指標實際上是一個棧對象,並非指標類型,在棧對象生命期即將結束時,智能指標通過解構函式釋放有它管理的堆記憶體。