天天看點

C++智能指針--weak_ptr

weak_ptr是對對象的一種弱引用,它不會添加對象的引用計數。weak_ptr和shared_ptr之間能夠互相轉換。shared_ptr能夠直接指派給week_ptr,week_ptr可通過調用lock函數來獲得shared_ptr(假設對象已經被釋放,則傳回一個空的shared_ptr)。

    單純使用shared_ptr有時會産生問題,考慮以下的代碼:

    在上面的代碼中,a和b互相進行引用。在a和b離開作用域時,a和b的引用計數都是1,記憶體沒有正常釋放。

這就是所謂的循環引用。

一般來講。解除這樣的循環引用有以下有三種可行的方法:

當僅僅剩下最後一個引用的時候須要手動打破循環引用釋放對象。

當parent的生存期超過children的生存期的時候。children改為使用一個普通指針指向parent。

使用弱引用的智能指針打破這樣的循環引用。

盡管這三種方法都可行,但方法1和方法2都須要程式猿手動控制。麻煩且easy出錯。

這裡主要介紹一下第三種方法和boost中的弱引用的智能指針boost::weak_ptr。解決方法是将A和B中的随意一個類聲明的變量改為week_ptr類型的。比方,改動類B後的代碼例如以下:

    改動後,b.m_a = a不會添加A對象的引用計數,是以a離開作用域時,引用計數為0。B對象的引用計數為2。在a和b離開作用域時,引用計數各減1後也為0。

強引用和弱引用

一個強引用當被引用的對象活着的話,這個引用也存在(就是說。當至少有一個強引用,那麼這個對象就不能被釋放)。boost::share_ptr就是強引用。

相對而言,弱引用當引用的對象活着的時候不一定存在。不過當它存在的時候的一個引用。弱引用并不改動該對象的引用計數,這意味這弱引用它并不正确對象的記憶體進行管理。在功能上類似于普通指針。然而一個比較大的差别是。弱引用能檢測到所管理的對象是否已經被釋放,進而避免訪問非法記憶體。

boost::weak_ptr

boost::weak_ptr<T>是boost提供的一個弱引用的智能指針,它的聲明能夠簡化例如以下:

能夠看到。boost::weak_ptr必須從一個boost::share_ptr或還有一個boost::weak_ptr轉換而來,這也說明,進行該對象的記憶體管理的是那個強引用的boost::share_ptr。boost::weak_ptr僅僅是提供了對管理對象的一個訪問手段。

boost::weak_ptr除了對所管理對象的基本訪問功能(通過get()函數)外,還有兩個經常使用的功能函數:expired()用于檢測所管理的對象是否已經釋放;lock()用于擷取所管理的對象的強引用指針。

通過boost::weak_ptr來打破循環引用

因為弱引用不更改引用計數,類似普通指針,僅僅要把循環引用的一方使用弱引用,就可以解除循環引用。對于上面的那個樣例來說,僅僅要把class B的定義進行改動就可以

最後值得一提的是,盡管通過弱引用指針能夠有效的解除循環引用。但這樣的方式必須在程式猿能預見會出現循環引用的情況下才幹使用,也能夠是說這個不過一種編譯期的解決方式,假設程式在執行過程中出現了循環引用,還是會造成記憶體洩漏的。是以,不要覺得隻要使用了智能指針便能杜絕記憶體洩漏。

畢竟。對于C++來說。因為沒有垃圾回收機制,記憶體洩漏對每個程式猿來說都是一個很頭痛的問題。

繼續閱讀