智能指針(三十一)
下來我們來看個示例代碼
#include <iostream> #include <string> using namespace std; class Test { int i; public: Test(int i) { cout << "Test(int i)" << endl; this->i = i; } int value() { return i; } ~Test() { cout << "~Test()" << endl; } }; int main() { for(int i=0; i<5; i++) { Test* p = new Test(i); cout << p->value() << endl; } return 0; }
我們明顯看到在 main 函數中只 new 對象了,而沒有 delete 對象。我們看看運行結果
我們看到只是進行了構造函數,並沒有析構函數的打印。也就是說,有內存泄漏,但是有人會說我們的程序還是運行結束了,啥事都沒有。這是因為這個程序很短,如果程序在長時間運行後,便會產生問題,而且這類問題是最難調試的。
那麽我們就會思考了:我們到底需要的是一個什麽樣的指針的?需要一個特殊的指針,在指針生命周期結束時能主動釋放堆空間。一片堆空間最多只能由一個指針標識,必須杜絕指針運算和指針比較。那麽解決方案便是重載指針特征操作符(-> 和 *),只能通過類的成員函數重載,並且重載函數不能使用參數它只能定義一個重載函數。我們稱之為智能指針
#include <iostream> #include <string> using namespace std; class Test { int i; public: Test(int i) { cout << "Test(int i)" << endl; this->i = i; } int value() { return i; } ~Test() { cout << "~Test()" << endl; } }; class Pointer { Test* mp; public: Pointer(Test* p = NULL) { mp = p; } Pointer(const Pointer& obj) { mp = obj.mp; const_cast<Pointer&>(obj).mp = NULL; } Pointer& operator = (const Pointer& obj) { if( this != &obj ) { delete mp; mp = obj.mp; const_cast<Pointer&>(obj).mp = NULL; } return *this; } Test* operator -> () { return mp; } Test& operator * () { return *mp; } bool isNull() { return (mp == NULL); } ~Pointer() { delete mp; } }; int main() { Pointer p1 = new Test(5); cout << p1->value() << endl; Pointer p2 = p1; cout << p1.isNull() << endl; cout << p2->value() << endl; return 0; }
我們在程序中定義了一個 Pointer 類,進行了一系列的操作符重載。打印 p1 的值就肯定為 5,接著將 p1 賦值給 p2,那麽此時 p1 就應該為空了,因為一片空間只能有一個標識符。所以在第 78 行打印出的肯定是 1 了,最後打印的 p2 的值也就為 5 了。我們看看編譯結果
我們看到打印的結果和我們所分析的是一致的,並且它也只是進行了一次構造函數和一次析構函數。那麽關於智能指針這塊,我們還有條使用軍規:就是它只能用來指向堆空間中的對象或者變量!那麽我們在 C++ 中的智能指針是不是就類似於高級語言中的垃圾回收機制呢?當然是很相似啦。通過對智能指針的學習,總結如下:1、指針特征操作符(-> 和 *)可以被重載;2、重載指針特征符能夠使用對象代替指針;3、智能指針只能用於指向堆空間中的內存;4、智能指針的意義在於最大程度的避免內存問題。
歡迎大家一起來學習 C++ 語言,可以加我QQ:243343083。
智能指針(三十一)