【1】boost::weak_ptr簡介html
boost::weak_ptr屬於boost庫,定義在namespace boost中,包含頭文件 #include<boost/weak_ptr.hpp>即可以使用。ios
【2】boost::weak_ptr詳解程序員
智能指針boost::scope_ptr和智能指針boost::shared_ptr就徹底能夠解決全部單個對象內存的管理問題。函數
這兒咋還多出一個boost::weak_ptr,是否還有某些案例咱們沒有考慮到呢? 學習
回答:有。首先 boost::weak_ptr是專門爲boost::shared_ptr而準備的。 spa
有時候,咱們只關心可否使用對象,並不關心內部的引用計數。 指針
boost::weak_ptr是 boost::shared_ptr的觀察者(Observer)對象,觀察者?觀察者怎麼理解呢? code
觀察者意味着boost::weak_ptr只對boost::shared_ptr進行引用,而不改變其引用計數。 server
當被觀察的boost::shared_ptr失效後,相應的boost::weak_ptr也隨之失效。 htm
那麼,爲何須要這個觀察者呢?那還得從循環引用談起。
引用計數是一種便利的內存管理機制,但它有一個很大的缺點,那就是不能管理循環引用的對象。
示例代碼以下:
1 #include <iostream>
2 #include <boost/shared_ptr.hpp>
3 #include <boost/weak_ptr.hpp>
4
5 class parent; 6 class children; 7
8 typedef boost::shared_ptr<parent> parent_ptr; 9 typedef boost::shared_ptr<children> children_ptr; 10
11 class parent 12 { 13 public: 14 ~parent() { std::cout <<"destroying parent\n"; } 15
16 public: 17 children_ptr children; 18 }; 19
20 class children 21 { 22 public: 23 ~children() { std::cout <<"destroying children\n"; } 24
25 public: 26 parent_ptr parent; 27 }; 28
29
30 void test() 31 { 32 parent_ptr father(new parent()); 33 children_ptr son(new children); 34
35 father->children = son; 36 son->parent = father; 37 } 38
39 void main() 40 { 41 std::cout<<"begin test...\n"; 42 test(); 43 std::cout<<"end test.\n"; 44 }
運行該程序能夠看到:即便退出了test函數後,因爲parent和children對象互相引用,它們的引用計數都是1,不能自動釋放,而且此時這兩個對象再沒法訪問到。
這也就引發了C++中那臭名昭著的內存泄漏。
<1> 通常來說,解除這種循環引用有下面有三種可行的方法:
1. 當只剩下最後一個引用的時候須要手動打破循環引用釋放對象。
2. 當parent的生存期超過children的生存期的時候,children改成使用一個普通指針指向parent。
3. 使用弱引用的智能指針打破這種循環引用。
雖然這三種方法均可行,但方法1和方法2都須要程序員手動控制,麻煩且容易出錯。
下面主要介紹一下第三種方法和boost中的弱引用的智能指針boost::weak_ptr。
<2> 什麼是強引用和弱引用?
一個強引用是指當被引用的對象仍活着的話,這個引用也存在(也就是說,只要至少有一個強引用,那麼這個對象就不會也不能被釋放)。boost::share_ptr就是強引用。
相對而言,弱引用當引用的對象活着的時候不必定存在。僅僅是當它自身存在的時的一個引用。
弱引用並不修改該對象的引用計數,這意味這弱引用它並不對對象的內存進行管理。
在功能上相似於普通指針,然而一個比較大的區別是,弱引用能檢測到所管理的對象是否已經被釋放,從而避免訪問非法內存。
boost::weak_ptr boost::weak_ptr<T>是boost提供的一個弱引用的智能指針,它的聲明能夠簡化以下:
1 namespace boost 2 { 3 template<typename T> class weak_ptr 4 { 5 public: 6 template <typename Y>
7 weak_ptr(const shared_ptr<Y>& r); 8
9 weak_ptr(const weak_ptr& r); 10
11 ~weak_ptr(); 12
13 T* get() const; 14 bool expired() const; 15 shared_ptr<T> lock() const; 16 }; 17 }
能夠看到,boost::weak_ptr必須從一個boost::share_ptr或另外一個boost::weak_ptr轉換而來,這也說明,進行該對象的內存管理的是那個強引用的boost::share_ptr。
boost::weak_ptr只是提供了對管理對象的一個訪問手段。
boost::weak_ptr除了對所管理對象的基本訪問功能(經過get()函數)外,還有兩個經常使用的功能函數:
1. expired() 用於檢測所管理的對象是否已經釋放;
2. lock() 用於獲取所管理的對象的強引用指針。
<3> 經過boost::weak_ptr來打破循環引用
因爲弱引用不更改引用計數,相似普通指針,只要把循環引用的一方使用弱引用,便可解除循環引用。
對於上面的那個例子來講,只要把children的定義改成以下方式,便可解除循環引用:
1 class children 2 { 3 public: 4 ~children() { std::cout <<"destroying children\n"; } 5
6 public: 7 boost::weak_ptr<parent> parent; 8 };
【3】boost::weak_ptr總結
雖然經過弱引用指針能夠有效的解除循環引用,但這種方式必須在程序員能預見會出現循環引用的狀況下才能使用,也能夠是說這個僅僅是一種編譯期的解決方案。
若是程序在運行過程當中出現了循環引用,仍是會形成內存泄漏的。
所以,不要認爲只要使用了智能指針便能杜絕內存泄漏。
畢竟,對於C++來講,因爲沒有垃圾回收機制,內存泄漏對每個程序員來講都是一個很是頭痛的問題。
聲明:爲了便於個人理解和學習,文章有部分修改內容,原文轉自《 智能指針--weak_ptr 》,(我學習的大師哦~)
Good Good Study, Day Day Up.
順序 選擇 循環 總結