程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> c++ 11學習筆記--智能指針

c++ 11學習筆記--智能指針

編輯:C++入門知識

c++ 11學習筆記--智能指針


C++ 98的 std::auto_ptr已經被徹底遺棄了,取而代之的是unique_ptr、shared_ptr與weak_ptr。大部分時候我們自己手動申請內存方式內存都是沒有問題的,問題是如果程序很大了之後,一個復雜的對象,多次拷貝的代價非常高,很多地方都會使用到,只存在一份拷貝顯然是最好的,這個時候對象生命周期的管理就會很復雜,所以c++引入了智能指針。       任何事物都會有兩面性。       Shared_ptr   摘錄於Effective C++, 3rd Edition, Item 17: 在 standalone statements(獨立語句)中將 new 出來的 objects(對象)存入 smart pointers(智能指針) 比如   復制代碼 class Widget { public:     Widget() {         cout << "construct Widget!!!" << endl;     }     ;     ~Widget() {         cout << "destruct Widget!!!" << endl;     }     ; };     int priority() {     cout << "22222" << endl;     return 0; }   void processWidget(int priority,std::shared_ptr<Widget> pw) {    cout << "111111" << endl;   }   int main() {     processWidget(priority(),std::shared_ptr<Widget>(new Widget));          return 0; }  復制代碼 processWidget運行的過程應該是   1.     New Widget   2.           shared_ptr constructor   3.         Priority()   我在llvm上測試的結果也是這個執行順序   也許某些編譯器上可能執行的順序是     New Widget   Priority() //發生異常   shared_ptr constructor 就有可能有內存洩露       所以最好的辦法還是應該把new widget提到外面來寫,所以好的編碼習慣很重要。           2.循環引用   復制代碼 #include <iostream>   using namespace std; class A; class B; typedef std::shared_ptr<A> APtr; typedef std::shared_ptr<B> BPtr;   class A { public:     BPtr b;     ~A () {          cout << "A released" << endl;     } };   class B { public:     APtr a;     ~B () {         cout << "B released" << endl;     } };   int main () {     APtr a(new A());     BPtr b(new B());          a->b = b; // 1     b->a = a; // 2           cout << "over!!" << endl;     return 0; } 復制代碼 要解決這個問題就需要引入一個弱引用的智能指針了weak_ptr   復制代碼 class A; class B;   typedef std::shared_ptr<A> APtr; typedef std::shared_ptr<B> BPtr; typedef std::weak_ptr<A> AWeakPtr; typedef std::weak_ptr<B> BWeakPtr;   class A { public:     BWeakPtr b; // 注意這裡     ~A () {         cout << "A released" << endl;     }      };   class B { public:     AWeakPtr a; // 注意這裡     ~B () {         cout << "B released" << endl;     }      };   int main () {     APtr a(new A());     BPtr b(new B());          a->b = b;     b->a = a;          return 0;  } 復制代碼 這兩種指針其實和oc裡面的 strong, weak非常相識。        weak_ptr的另外一種用法   使用情景:當類對象被 shared_ptr 管理時,需要在類自己定義的函數裡把當前類對象作為參數傳給其他函數時,這時需要傳遞一個 shared_ptr ,否則就不能保持 shared_ptr 管理這個類對象的語義(因為有一個 raw pointer 指向這個類對象,而 shared_ptr 對類對象的這個引用沒有計數,很有可能 shared_ptr 已經把類對象資源釋放了,而那個調用函數還在使用類對象——顯然,這肯定會產生錯誤)。《摘錄:http://blog.csdn.net/zhongguoren666/article/details/8617436》       直接看官網的例子吧:   《http://en.cppreference.com/w/cpp/memory/enable_shared_from_this》       復制代碼 #include <memory> #include <iostream>   struct Good: std::enable_shared_from_this<Good> {     std::shared_ptr<Good> getptr() {         return shared_from_this();     } };   struct Bad {     std::shared_ptr<Bad> getptr() {         return std::shared_ptr<Bad>(this);     }     ~Bad() { std::cout << "Bad::~Bad() called\n"; } };   class CObj: public std::enable_shared_from_this<CObj> {     friend class CObjMgr; protected:     CObj() {}   // 只有CObjMgr可以創建與刪除     ~CObj(){} };     int main() {     // Good: the two shared_ptr's share the same object     std::shared_ptr<Good> gp1(new Good);     std::shared_ptr<Good> gp2 = gp1->getptr();     std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';          // Bad, each shared_ptr thinks it's the only owner of the object     std::shared_ptr<Bad> bp1(new Bad);     std::shared_ptr<Bad> bp2 = bp1->getptr();     std::cout << "bp2.use_count() = " << bp2.use_count() << '\n'; } // UB: double-delete of Bad 復制代碼 1.絕對不能在構造函數中調用shared_from_this()   因為shared_ptr裡面初始化enable_shared_from_this的成員weak_ptr,      這個時候weak_ptr還是空值。        2.為什麼內部不能用this指針   因為我們程序中用shared_ptr來管理指針,如果我們在類的內部傳遞的過程中用原始指針,這樣類內部的引用shared_ptr不會察覺到,因為有可能我們傳進去的時候已經被shared_ptr釋放掉了。       unique_ptr   相對就要單純許多了,unique_ptr“唯一”擁有其所指對象,只能有一個unique_ptr指向給定對象(通過禁止拷貝語義、只有移動語義來實現)。       代替普通指針   復制代碼 void foo()   {//不安全的代碼       X *px = new X;       // do something, exception may occurs   delete px; // may not go here        }    unique_ptr<X> px(new X);   復制代碼 在函數中返回對象       unique_ptr<X> foo()   {       unique_ptr<X> px(new X);       // do something       return px; //移動語義   }   放入容器中   vector<unique_ptr<string>> vs { new string{“1111”}, new string{“2222”},new string{“3333”}  };     vector<unique_ptr<string>>v;   unique_ptr<string> test(new string("11111"));   v.push_back(std::move(test));//使用移動語法 支持直接持有數組   std::shared_ptr<int> p(new int[10],     [](int* p){         delete[] p;     }); //或者使用helper std::shared_ptr<int> p(new int[10],std::default_delete<int[]>());

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved