智能指針Boost.smart_ptr學習1--爲什麼使用智能指針

我們學習C++都知道智能指針,例如STL中的std::auto_ptr,但是爲什麼要使用智能指針,使用它能帶給我們什麼好處呢?

最簡單的使用智能指針可以不會因爲忘記delete指針而造成內存泄露。還有如果我們開發或者使用第三方的lib中的某些函數需要返回指針,這樣的返回的指針被client使用的時候,lib就會失去對返回的指針的控制,這樣delete的指針的任務一般就會交給調用方client,但是如果 client忘記調用delete或是調用的時機不正確,都有可能導致問題,在這種情況下就最好使用智能指針。還有使用智能指針可以保證異常安全,保證程序在有異常拋出時仍然無內存泄露。
   
std::auto_ptr很多的時候並不能滿足我們的要求,比如她不能用在STL的container中。boost的smart_ptr中提供了4種智能指針和2種智能指針數組來作爲std::auto_ptr的補充。   

  • shared_ptr<boost/shared_ptr.hpp>:使用shared_ptr進行對象的生存期自動管理,使得分享資源所有權變得有效且安全. 
  • scoped_ptr<boost/scoped_ptr.hpp>: 用於確保能夠正確地刪除動態分配的對象。scoped_ptr 有着與std::auto_ptr類似的特性,而最大的區別在於它不能轉讓所有權而auto_ptr可以。事實上,scoped_ptr永遠不能被複制或被賦值!scoped_ptr 擁有它所指向的資源的所有權,並永遠不會放棄這個所有權。 
  • weak_ptr<boost/weak_ptr.hpp>:weak_ptr 是 shared_ptr 的觀察員。它不會干擾shared_ptr所共享的所有權。當一個被weak_ptr所觀察的 shared_ptr 要釋放它的資源時,它會把相關的 weak_ptr的指針設爲空。使用此輔助指針一般是防止懸空指針。
  • intrusive_ptr<boost/intrusive_ptr.hpp>:shared_ptr的插入是版本,一般不使用,因爲需要對使用此指針的類型中增加ref計數功能。但是可以保證不增加指針的大小。
  • scoped_array<boost/scoped_array.hpp>: scoped_array 爲數組做了scoped_ptr爲單個對象的指針所做的事情:它負責釋放內存。shared_array<boost/shared_array.hpp>: shared_array 用於共享數組所有權的智能指針。一般指向std::vector的shared_ptr提供了比shared_array更多的靈活性,所以一般使用 std::vector<shared_ptr>。




Smart_ptr庫如何改進你的程序?

  • 使用shared_ptr進行對象的生存期自動管理,使得分享資源所有權變得有效且安全。
  • 使用weak_ptr可以安全地觀測共享資源,避免了懸掛的指針。
  • 使用scoped_ptr 和 scoped_array限制資源的使用範圍,使得代碼更易於編寫和維護,並有助於寫出異常安全的代碼。


智能指針解決了資源生存期管理的問題(尤其是動態分配的對象). 智能指針有各種不同的風格。多數都有一種共同的關鍵特性:自動資源管理。這種特性可能以不同的方式出現:如動態分配對象的生存期控制,和獲取及釋放資源 (文件, 網絡連接)。Boost的智能指針主要針對第一種情況,它們保存指向動態分配對象的指針,並在正確的時候刪除這些對象。你可能覺得奇怪爲什麼這些智能指針不多做一點工作。它們不可以很容易就覆蓋所有資源管理的不同情況嗎?是的,它們可以(在一定範圍內它們可以),但不是沒有代價的。通用的解決方案意味着更高的複雜性,而對於Boost的智能指針,可用性比靈活性具有更高的優先級。但是,通過對可定製刪除器的支持,Boost的最智能的智能指針(boost::shared_ptr)可以支持那些不是使用delete進行析構的資源。Boost.Smart_ptr的五個智能指針類型是專門特製的,適用於每天的編程中最常見的需求。

何時我們需要智能指針?

有三種典型的情況適合使用智能指針:

  • 資源所有權的共享
  • 要編寫異常安全的代碼時
  • 避免常見的錯誤,如資源泄漏


共享所有權是指兩個或多個對象需要同時使用第三個對象的情況。這第三個對象應該如何(或者說何時)被釋放?爲了確保釋放的時機是正確的,每個使用這個共享資源的對象必須互相知道對方,才能準確掌握資源的釋放時間。從設計或維護的觀點來看,這種耦合是不可行的。更好的方法是讓這些資源所有者將資源的生存期管理責任委派給一個智能指針。當沒有共享者存在時,智能指針就可以安全地釋放這個資源了。

異常安全,簡單地說就是在異常拋出時沒有資源泄漏並保證程序狀態的一致性。如果一個對象是動態分配的,當異常拋出時它不會自動被刪除。由於棧展開以及指針離開作用域,資源可以會泄漏直至程序結束(即使是程序結束時的資源回收也不是由語言所保證的)。不僅可能程序會由於內存泄漏而耗盡資源,程序的狀態也可能變得混亂。智能指針可以自動地爲你釋放這些資源,即使是在異常發生的情況下。

避免常見的錯誤。忘記調用 delete 是書本中最古老的錯誤(至少在這本書中)。一個智能指針不關心程序中的控制路徑;它只關心在它所指向的對象的生存期結束時刪除它。使用智能指針,你不再需要知道何時刪除對象。並且,智能指針隱藏了釋放資源的細節,因此使用者不需要知道是否要調用 delete, 有些特殊的清除函數並不總是刪除資源的。

安全和高效的智能指針是程序員的軍火庫中重要的武器。雖然C++標準庫中提供了 std::auto_ptr, 但是它不能完全滿足我們對智能指針的需求。例如,auto_ptr不能用作STL容器的元素。Boost的智能指針類填充了標準所留下來的缺口。

本章主要關注 scoped_ptr, shared_ptr, intrusive_ptr, 和 weak_ptr. 雖然剩下的 scoped_array 和 shared_array 有時候也很有用,但它們用的不是很多,而且它們與已討論的非常相近,這裏就不重複討論它們了。

Smart_ptr如何適應標準庫?

Smart_ptr庫已被提議包含進標準庫中,主要有以下三個原因:

  • 標準庫現在只提供了一個auto_ptr, 它僅是一類智能指針,僅僅覆蓋了智能指針族譜中的一個部分。shared_ptr 提供了不同的,也是更重要的功能。
  • Boost的智能指針專門爲了與標準庫良好合作而設計,並可作爲標準庫的自然擴充。例如,在 shared_ptr之前,還沒有一個標準的智能指針可用作容器的元素。
  • 長久以來,現實世界中的程序員已經在他們的程序中大量使用這些智能指針類,它們已經得到了充分的驗證。


以上原因使得Smart_ptr庫成爲了C++標準庫的一個非常有用的擴充。Boost.Smart_ptr的 shared_ptr (以及隨同的助手 enable_shared_from_this) 和 weak_ptr 已被收入即將發佈的Library Technical Report。

發佈了13 篇原創文章 · 獲贊 6 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章