C++ 智能指針學習
阿新 • • 發佈:2017-06-07
release new div str 我們 指針的引用 機制 cin 轉化
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
/* SmartPtr.cpp Author: Michael Joessy Date: 2017-06-07 Marks: C++裏面的四個智能指針: auto_ptr, shared_ptr, weak_ptr, unique_ptr; 其中後三個是C++11支持,並且第一個已經被C++11棄用。 為什麽要使用智能指針: 我們知道C++的內存管理是讓很多人頭疼的事,當我們寫一個new語句時,一般就會立即把delete語句直接也寫了; 但是我們不能避免程序還未執行到delete時就跳轉了或者在函數中沒有執行到最後的delete語句就返回了; 如果我們不在每一個可能跳轉或者返回的語句前釋放資源,就會造成內存泄露。 使用智能指針可以很大程度上的避免這個問題: 因為智能指針就是一個類,當超出了類的作用域是,類會自動調用析構函數,析構函數會自動釋放資源。 */ #include <memory> #include <iostream> #include <string> using namespace std; using namespace std::tr1; //auto_ptr http://www.cplusplus.com/reference/memory/auto_ptr/ //unique_ptr http://www.cplusplus.com/reference/memory/unique_ptr/ //share_ptr http://www.cplusplus.com/reference/memory/share_ptr/ //weak_ptr http://www.cplusplus.com/reference/memory/weak_ptr/ { public: TestSmartPtr(string str) { m_str = str; cout << "TestSmartPtr creat\n"; } ~TestSmartPtr() { cout << "TestSmartPtr delete:" << m_str <<endl; } string& getStr() { return m_str; } void setStr(string str) { m_str = str; } void print() { cout << m_str << endl; } private: string m_str; }; class classB; class classA { public: //shared_ptr<classB> pB_; weak_ptr<classB> pB_; ~classA() { cout << "classA delete\n"; } }; class classB { public: shared_ptr<classA> pA_; ~classB() { cout << "classB delete\n"; } }; int main(void) { //auto_ptr /*成員函數get()返回一個原始的指針,成員函數reset()重新綁定指向的對象,而原來的對象則會被釋放 判斷一個智能指針是否為空應該使用if(pTestAutoPtr.get() == NULL) 成員函數release()只是把智能指針賦值為空,但是它原來指向的內存並沒有被釋放,相當於它只是釋放了對資源的所有權 當我們想要在中途釋放資源,而不是等到智能指針被析構時才釋放,我們可以使用pTestAutoPtr.reset(); 語句。 */ #if 0 auto_ptr<TestSmartPtr> pTestAutoPtr(new TestSmartPtr("315")); if(pTestAutoPtr.get() == NULL) { cout << "pTestAutoPtr = NULL\n"; } pTestAutoPtr->setStr("Michael "); pTestAutoPtr->print(); pTestAutoPtr.get()->print(); pTestAutoPtr->getStr() += "Joessy !"; (*pTestAutoPtr).print(); pTestAutoPtr.reset(new TestSmartPtr("315")); pTestAutoPtr->print(); pTestAutoPtr.release(); #endif //unique_ptr /*unique_ptr 是一個獨享所有權的智能指針,它提供了嚴格意義上的所有權,包括: 1、擁有它指向的對象 2、無法進行復制構造,無法進行復制賦值操作。即無法使兩個unique_ptr指向同一個對象。但是可以進行移動構造和移動賦值操作 3、保存指向某個對象的指針,當它本身被刪除釋放的時候,會使用給定的刪除器釋放它指向的對象 unique_ptr 可以實現如下功能: 1、為動態申請的內存提供異常安全 2、動態申請的內存所有權傳遞給某函數 3、從某個函數返回動態申請內存的所有權 4、在容器中保存指針 5、auto_ptr應該具有的功能 */ #if 0 unique_ptr<int> up(p); unique_ptr<TestSmartPtr> pTestUniquePtr1(new TestSmartPtr("123")); unique_ptr<TestSmartPtr> pTestUniquePtr2(new TestSmartPtr("456")); pTestUniquePtr1->print(); pTestUniquePtr2 = std::move(pTestUniquePtr1); //不能直接pTestUniquePtr2 = pTestUniquePtr1 if(pTestUniquePtr1 == NULL) { cout << "pTestUniquePtr1 = NULL\n"; } TestSmartPtr* p = pTestUniquePtr2.release(); p->print(); pTestUniquePtr1.reset(p); pTestUniquePtr1->print(); #endif //share_ptr /* 從share中就可以看出資源可以被多個指針共享,它使用計數機制來表明資源被幾個指針共享。 可以通過成員函數use_count()來查看資源的所有者個數。 除了可以通過new來構造,還可以通過傳入auto_ptr, unique_ptr,weak_ptr來構造。 當我們調用release()時,當前指針會釋放資源所有權,計數減一。 當計數等於0時,資源會被釋放。 */ #if 0 shared_ptr<TestSmartPtr> pTestSharePtr1(new TestSmartPtr("123")); shared_ptr<TestSmartPtr> pTestSharePtr2(new TestSmartPtr("456")); cout << pTestSharePtr2->getStr()<<endl; cout << pTestSharePtr2.use_count()<<endl; pTestSharePtr1 = pTestSharePtr2; //"456"引用次數加1,"123"銷毀 pTestSharePtr1->print(); cout << pTestSharePtr2.use_count() << endl; cout << pTestSharePtr1.use_count() << endl; pTestSharePtr1.reset(); pTestSharePtr2.reset(); //此時"456"銷毀 #endif //weak_ptr /*weak_ptr是用來解決shared_ptr相互引用時的死鎖問題; 如果說兩個shared_ptr相互引用,那麽這兩個指針的引用計數永遠不可能下降為0,資源永遠不會釋放。 它是對對象的一種弱引用,不會增加對象的引用計數,和shared_ptr之間可以相互轉化; shared_ptr可以直接賦值給它,它可以通過調用lock函數來獲得shared_ptr。 */ #if 0 shared_ptr<classB> pB(new classB()); shared_ptr<classA> pA(new classA()); pB->pA_ = pA; pA->pB_ = pB; cout << pB.use_count() << endl; cout << pA.use_count() << endl; #endif /*說明: pA與pB之間互相引用,兩個資源的引用計數為2; 當要跳出函數時,智能指針pA與pB析構時兩個資源引用計數會減一; 但是兩者引用計數還是為1,導致跳出函數時資源沒有被釋放(classA與classB的析構函數沒有被調用). 如果把其中一個改為weak_ptr就可以了,我們把類A裏面的shared_ptr<B> pB_; 改為weak_ptr<B> pb_; 這樣的話,資源classB的引用開始就只有1; 當pB析構時,B的計數變為0,B得到釋放; B釋放的同時也會使A的計數減一; 同時pa析構時使A的計數減一,那麽A的計數為0,A得到釋放。 */ cin.get(); return 0; } |
C++ 智能指針學習