多線程程序經常會遇到在某個線程A創建了一個對象,這個對象需要在線程B使用,
在沒有shared_ptr時,因為線程A,B結束時間不確定,即在A或B線程先釋放這個對象都有可能造成另一個線程崩潰,
所以為了省時間一般都是任由這個內存泄漏發生.
當然也可以經過復雜的設計,由一個監控線程來統一刪除,
但這樣會增加代碼量和復雜度.這下好了,shared_ptr 可以方便的解決問題,因為它是引用計數和線程安全的.
shared_ptr不用手動去釋放資源,它會智能地在合適的時候去自動釋放。
我們來測試看看效果
1 //C++11 shared_ptr 智能指針 的使用,避免內存泄露 2 #include <iostream> 3 #include <memory> 4 using namespace std; 5 6 #define _PRT(T) std::shared_ptr<T> 7 8 //定義 shared_ptr<T> 的智能指針 9 #define _PRTO(T,N,...) std::shared_ptr<T> N(new T(##__VA_ARGS__)) 10 11 //定義 shared_ptr<T> 的數組智能指針 12 #define _PRTA(T,N,n) std::shared_ptr<T> N(new T[n]) 13 14 class A { 15 public: 16 int n; 17 A(int n):n(n) { 18 cout <<n<< " construct A!!!" << endl; 19 } 20 ; 21 ~A() { 22 cout <<n<< " destruct A!!!" << endl; 23 } 24 ; 25 void Out(){ cout << n * 2 << endl; } 26 }; 27 class B : public A { 28 public: 29 B(int n):A(n) { 30 cout <<n<< " construct B!!!" << endl; 31 } 32 ; 33 ~B() { 34 cout <<n<< " destruct B!!!" << endl; 35 } 36 ; 37 _PRT(A) geta(int n) { _PRTO(A,a,n); return a; } 38 39 void chars() { 40 //使用智能指針指向 char[],以自動釋放 41 _PRTA(char,p,1024*1024); 42 strcpy(p.get(), "std::shared_ptr<char*>"); 43 printf(p.get()); 44 } 45 46 }; 47 int main() { 48 B* ptrB0 = new B(1); 49 ptrB0->Out(); 50 51 _PRT(B) ptrB1(new B(2)); 52 ptrB1->Out(); 53 _PRT(A) a = ptrB1->geta(5); 54 a->Out(); 55 //復制了指針,增加引用計數 56 _PRT(B) ptrB2 = ptrB1;57 _PRT(A) b = ptrB2->geta(6); 58 b->Out(); 59 ptrB2->Out(); 60 61 //使用智能指針,會自動釋放 62 for(int i=100;i;i--) 63 ptrB2->chars(); 64 }
測試程序中循環了100次,每次 new 了1Mb的內存, 調試過程中可以看到每次循環完內存都沒有增長;
並且main執行完后,直接new的 類1 沒有釋放, 而類2自動釋放了,
並且 如果有賦值給其他shared_ptr指針, 指針指向的對象不會釋放,即指針指向的對象不會失效, 除非所有指向此對象的指針都無效了/不用了, 此對象才會自動釋放.