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

智能指針

編輯:C++入門知識

智能指針就是存儲指向堆上分配的對象的指針,行為上與C++的原生指針基本一致,區別是不需要管理對象的銷毀。智能指針可以選擇在適當的時機銷毀對象,可以大幅降低空懸指針和野指針等錯誤。所有智能指針如果是非類成員,一般都是棧上分配的對象。這裡介紹boost庫的智能指針,主要有:   1. scoped_ptr 概念上講,智能指針意味著持有它所指向對象的擁有權,有責任在該對象不在需要時對其銷毀。scoped_ptr只提供了RAII機制,對它指向的對象具有唯一的擁有權,不會被共享和轉移。這是通過不可拷貝實現的,所以scoped無法存放到stl容器中。指向的對象在scoped_ptr析構或者reset後會被釋放。scoped_ptr實現很簡單,基本與原生指針性能差不多。scoped_ptr用在類成員時,可以避免在析構函數中釋放指針。     [cpp]  class A {   ...   private:       B *obj;   };     class A { ... private:     B *obj; }; 類A的析構函數不得不對指針obj進行delete操作,而改成scoped_ptr則可以避免:     [cpp]  class A {   ...   private:       boost::scoped_ptr<B> obj;   };     class A { ... private:     boost::scoped_ptr<B> obj; };2. shared_ptr 以引用計數的方式共享指針的擁有權。當最後一個shared_ptr被銷毀時,指向的對象也會被銷毀。由於使用引用計數,無法解決循環引用的問題。shared_ptr實現了拷貝構造函數和賦值運算符,可以存放到stl容器中。同時,也實現了比較運算符,可以存放到關聯容器中。   如果T *可以隱式轉化(通過static_cast)為U *,那麼shared_ptr<T>也可以隱式轉化為shared_ptr<U>。   線程安全反面,shared_ptr支持:a. 並發讀,b. 並發寫多個不同的實例,c. 不支持並發讀寫同一個實例(需加鎖)。   下列程序存在循環引用:       [cpp]   #include <iostream>                                                                                                                                    #include <boost/shared_ptr.hpp>                                                                                                                     #include <boost/weak_ptr.hpp>                                                                                                                          using namespace std;                                                                                                                               using namespace boost;                                                                                                                                    class B;                                                                                                                                                 class A {                                                                                                                                          public:                                                                                                                                                ~A() {                                                                                                                                                 cout << "ref count of B: " << bptr.use_count() << endl;                                                                                            cout << "deconstruct A" << endl;                                                                                                               }                                                                                                                                                         shared_ptr<B> bptr;                                                                                                                            };                                                                                                                                                    class B {                                                                                                                                          public:                                                                                                                                                ~B() {                                                                                                                                                 cout << "ref count of A: " << aptr.use_count() << endl;                                                                                            cout << "deconstruct B" << endl;                                                                                                               }                                                                                                                                                     shared_ptr<A> aptr;                                                                                                                          };                                                                                                                                                    void test()                                                                                                                                        {                                                                                                                                                      cout << "begin" << endl;                                                                                                                           shared_ptr<A> aptr(new A);                                                                                                                         shared_ptr<B> bptr(new B);                  aptr->bptr = bptr;          bptr->aptr = aptr;                                                                                                                                   cout << "ref count of bptr: " << bptr.use_count() << endl;                                                                                         cout << "ref count of aptr: " << aptr.use_count() << endl;                                                                                           cout << "end" << endl;                                                                                                                         }                                                                                                                                                     int main()                                                                                                                                         {                                                                                                                                                      test();                                                                                                                                            cout << "after test" << endl;                                                                                                                  }        #include <iostream>                                                                                                                                #include <boost/shared_ptr.hpp>                                                                                                                  #include <boost/weak_ptr.hpp>                                                                                                                      using namespace std;                                                                                                                             using namespace boost;                                                                                                                                class B;                                                                                                                                             class A {                                                                                                                                        public:                                                                                                                                              ~A() {                                                                                                                                               cout << "ref count of B: " << bptr.use_count() << endl;                                                                                          cout << "deconstruct A" << endl;                                                                                                             }                                                                                                                                                  shared_ptr<B> bptr;                                                                                                                          };                                                                                                                                                 class B {                                                                                                                                        public:                                                                                                                                              ~B() {                                                                                                                                               cout << "ref count of A: " << aptr.use_count() << endl;                                                                                          cout << "deconstruct B" << endl;                                                                                                             }                                                                                                                                                  shared_ptr<A> aptr;                                                                                                                        };                                                                                                                                                 void test()                                                                                                                                      {                                                                                                                                                    cout << "begin" << endl;                                                                                                                         shared_ptr<A> aptr(new A);                                                                                                                       shared_ptr<B> bptr(new B);           aptr->bptr = bptr;        bptr->aptr = aptr;                                                                                                                                cout << "ref count of bptr: " << bptr.use_count() << endl;                                                                                       cout << "ref count of aptr: " << aptr.use_count() << endl;                                                                                        cout << "end" << endl;                                                                                                                       }                                                                                                                                                  int main()                                                                                                                                       {                                                                                                                                                    test();                                                                                                                                          cout << "after test" << endl;                                                                                                                }        運行程序,可以發現A和B都沒有被析構。下面通過weak_ptr解決這種循環引用的問題。       [plain]  begin   ref count of bptr: 2   ref count of aptr: 2   end   after test     begin ref count of bptr: 2 ref count of aptr: 2 end after test 3. weak_ptr weak_ptr不管理對象的生命周期,但是可以感知一個對象的生死。weak_ptr是弱引用,用它指向一個對象,不會增加其引用計數。weak_ptr指向的對象底層有shared_ptr管理,要通過weak_ptr訪問這個對象,必須構造成shread_ptr才行。具體可以通過shared_ptr的構造函數或者是lock方法。當最後一個指向該對象的shared_ptr被銷毀時,該對象也會被銷毀。此時,調用shared_ptr的構造函數會拋出boost::bad_weak_ptr異常,lock返回的shared_ptr是空的。   weak_ptr實現了拷貝構造函數、賦值運算符和比較運算符所以可以放入stl容器和關聯容器中。   下面看一下,weak_ptr是如何解決循環引用,將類B中指向aptr的shared_ptr改為weak_ptr即可。     [cpp]   #include <iostream>                                                                                                                                                                                                                                                                                    #include <boost/shared_ptr.hpp>                                                                                                                     #include <boost/weak_ptr.hpp>                                                                                                                                                                                                                                                                                                                                                                                                                             using namespace std;                                                                                                                               using namespace boost;                                                                                                                                                                                                                                                                                class B;                                                                                                                                                                                                                                                                                              class A {                                                                                                                                          public:                                                                                                                                                ~A() {                                                                                                                                                 cout << "ref count of B: " << bptr.use_count() << endl;                                                                                            cout << "deconstruct A" << endl;                                                                                                               }                                                                                                                                                                                                                                                                                                     shared_ptr<B> bptr;                                                                                                                            };                                                                                                                                                                                                                                                                                                    class B {                                                                                                                                          public:                                                                                                                                                ~B() {                                                                                                                                                 cout << "ref count of A: " << aptr.use_count() << endl;                                                                                            cout << "deconstruct B" << endl;                                                                                                               }                                                                                                                                                                                                                                                                   weak_ptr<A> aptr;                                                                                                                              };                                                                                                                                                                                                                                                                                                    void test()                                                                                                                                        {                                                                                                                                                      cout << "begin" << endl;                                                                                                                           shared_ptr<A> aptr(new A);                                                                                                                         shared_ptr<B> bptr(new B);                                                                                                                                                                                                                                                                            weak_ptr<A> waptr(aptr);                                                                                                                                                                                                                                                                              aptr->bptr = bptr;                                                                                                                                 bptr->aptr = waptr;                                                                                                                                                                                                                                                                                   cout << "ref count of bptr: " << bptr.use_count() << endl;                                                                                         cout << "ref count of aptr: " << waptr.use_count() << endl;                                                                                                                                                                                                                                           cout << "end" << endl;                                                                                                                         }                                                                                                                                                                                                                                                                                                     int main()                                                                                                                                         {                                                                                                                                                      test();                                                                                                                                            cout << "after test" << endl;                                                                                                                  }        #include <iostream>                                                                                                                                                                                                                                                                               #include <boost/shared_ptr.hpp>                                                                                                                  #include <boost/weak_ptr.hpp>                                                                                                                                                                                                                                                                                                                                                                                                                      using namespace std;                                                                                                                             using namespace boost;                                                                                                                                                                                                                                                                            class B;                                                                                                                                                                                                                                                                                          class A {                                                                                                                                        public:                                                                                                                                              ~A() {                                                                                                                                               cout << "ref count of B: " << bptr.use_count() << endl;                                                                                          cout << "deconstruct A" << endl;                                                                                                             }                                                                                                                                                                                                                                                                                                 shared_ptr<B> bptr;                                                                                                                          };                                                                                                                                                                                                                                                                                                class B {                                                                                                                                        public:                                                                                                                                              ~B() {                                                                                                                                               cout << "ref count of A: " << aptr.use_count() << endl;                                                                                          cout << "deconstruct B" << endl;                                                                                                             }                                                                                                                                                                                                                                                                 weak_ptr<A> aptr;                                                                                                                            };                                                                                                                                                                                                                                                                                                void test()                                                                                                                                      {                                                                                                                                                    cout << "begin" << endl;                                                                                                                         shared_ptr<A> aptr(new A);                                                                                                                       shared_ptr<B> bptr(new B);                                                                                                                                                                                                                                                                        weak_ptr<A> waptr(aptr);                                                                                                                                                                                                                                                                          aptr->bptr = bptr;                                                                                                                               bptr->aptr = waptr;                                                                                                                                                                                                                                                                               cout << "ref count of bptr: " << bptr.use_count() << endl;                                                                                       cout << "ref count of aptr: " << waptr.use_count() << endl;                                                                                                                                                                                                                                       cout << "end" << endl;                                                                                                                       }                                                                                                                                                                                                                                                                                                 int main()                                                                                                                                       {                                                                                                                                                    test();                                                                                                                                          cout << "after test" << endl;                                                                                                                }   運行結果:     [plain]   begin   ref count of bptr: 2   ref count of aptr: 1   end   ref count of B: 1   deconstruct A   ref count of A: 0   deconstruct B   after test     begin ref count of bptr: 2 ref count of aptr: 1 end ref count of B: 1 deconstruct A ref count of A: 0 deconstruct B after test 可以看到A和B都被析構了,並且在test函數的結尾處,檢查aptr的引用計數是1,而bptr是2,這是因為weak_ptr指向這個對象,不會引起引用計數的改變。    

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