2 智慧型指標

2021-09-06 11:46:24 字數 2544 閱讀 2951

為什麼需要智慧型指標?

乙個類庫的產生勢必有其被觸發的動機,正如某句經典語所云:在這個世界上,沒有無緣無故的愛,也沒有無緣無故的恨。

同樣的,在c++世界裡,也不是無緣無故的出現智慧型指標。

搞清楚智慧型指標的設計動機,對於正確的理解智慧型指標工作原理、設計思想、以及適用場合是有著非常直接的幫助。

所以,讓我們先來看一看:為什麼需要智慧型指標?

從本質上來說,智慧型指標的引入實際上是為了解決乙個問題:

為了有效準確地管理程式執行過程中動態申請的記憶體資源,以妥善地解決動態申請到的記憶體的擁有權問題。

(為了便於描述,下文中將智慧型指標所要解決的問題簡述為「動態記憶體擁有權問題」)

在c++程式中,我們經常會出於這樣或那樣的原因,需要從系統堆(heap)中動態申請記憶體,用於存放一些只有在程式執行期間才能確定其大小的資料物件。

而在現實的計算機系統中,記憶體資源總量是很有限的,因此有了申請,就得要有釋放,只有那樣,才能好借好還,為應用程式可以從heap中持續申請獲得記憶體做好鋪墊。

如果,對於每乙個動態記憶體申請點來說,我們都能夠清晰地明確其釋放點,那麼,動態申請記憶體的釋放似乎並不是一件值得特殊考慮的事情。

但是,實際軟體系統中的資料依賴關係往往非常複雜,很多時候,不太容易確定一塊動態申請到的記憶體到底到何時才真的可以允許釋放掉。

比如說,對於同一塊動態申請到的記憶體,在程式中往往會有多個引用點,這種多指一的關係,就提出了額外的資料一致性的要求,

只有在確保多個引用點都不會再訪問這塊動態記憶體的前提下,才可以安全地將其釋放掉。

再比如說,c++中的異常處理機制強化了程式設計師處理錯誤場景的能力,但是異常這種機制在本質上類似於goto語句的靈活性也為動態記憶體的釋放增加了管理上的負擔。

當然,為了精準無誤的手工釋放動態申請到的記憶體,程式設計師可以仔細地對程式中的資料依賴關係作仔細地考量和設計,從而確保安全準確地手工釋放動態記憶體。

但是,動態記憶體的擁有權問題往往並不是軟體系統的核心競爭力所在(我們可以說記憶體管理是乙個軟體系統的基礎設施的重要構成部分,但說它是乙個軟體系統的核心競爭力所在,

似乎就不太合適了,

當然,對於以記憶體管理為市場賣點的軟體產品是個例外,比如smartheap),

在軟體開發過程中,花費過多精力來解決動態記憶體的擁有權問題,看起來多少有些不划算。

如果能夠將「動態記憶體擁有權」這個問題的複雜性,從軟體產品本身的複雜性中分離出來,由專門的人或團隊來負責實現,實際上是非常有利於軟體的模組化和復用性的。

畢竟,從本質上來看,動態記憶體的擁有權和一款軟體產品本身所要解決的目標問題在相當大程度上是正交的,將其分解開來,分而治之從軟體工程學的角度來看實在是個不賴的選擇。

所以說,智慧型指標正是為了專門解決「動態記憶體擁有權」這一問題的產物。

真理:道理都不是看,讀或者聽懂的!

智慧型指標怎樣解決了「動態記憶體擁有權」問題?

那麼,具體來說,智慧型指標以什麼樣的方式解決了"動態記憶體擁有權"的問題呢?

概要地來說,智慧型指標通過增加乙個封裝類,讓指向動態記憶體的指標在封裝類的物件層面具備了值語義(關於值語義這個概念,請參見隨筆《值語義與物件語義》),從而解決了指標所指向的動態記憶體的擁有權問題。

進一步深入**,我們發現動態記憶體指標之所以不滿足值語義,是因為動態記憶體指標涉及到其指向的動態記憶體的擁有權的管理,而在將乙個動態記憶體指標所指向的動態記憶體位址複製到目標指標的同時,

指標所指向的動態記憶體的擁有權也被該目標指標共享,對同一片動態記憶體區域,存在兩個引用點,這就帶來了同步性的問題,對源指標和目標指標的操作不是完全正交的。

從本質上來說,給定一塊動態記憶體區域,如果存在多個指向它的物件,動態記憶體擁有權的同步問題是不可迴避的。

不過,我們是不是可以將這個擁有權的同步問題封裝在有限的範圍,從而在物件介面層面讓客戶端的**獲得值語義的使用體驗呢?這正是智慧型指標的設計理念。

通常來說,智慧型指標會提供乙個封裝類,對c++中原生的指標進行封裝,在封裝類內部,通過乙個計數器來協調指向同一塊動態記憶體區域的多個智慧型指標之間的所有權關係。

而封裝類會提供客戶端**通常會施加在原生指標上的絕大多數操作介面,比如提領操作,位址比較操作,等等。

這樣,在保證跟原生指標相近的操作體驗的同時,簡化了動態記憶體的管理負擔。

注:針對不同的應用場景,實際的智慧型指標也存在若干不同的分類,比如:

1> 支援毀壞式複製語義及raii的智慧型指標,典型代表是std::auto_ptr(請參見隨筆《 [3]智慧型指標std::auto_ptr 》);

2> 不支援值語義,只提供raii的智慧型指標,典型代表是boost::scope_ptr(請參見隨筆《 [4]智慧型指標boost::scoped_ptr 》),其類似於stl中的unique_ptr智慧型指標;

3> 支援值語義,提供引用計數機制及raii支援的智慧型指標,典型代表是boost::shared_ptr(請參見隨筆《 [5]智慧型指標boost::shared_ptr 》),其類似於stl中的shared_ptr智慧型指標;

4> 為了解決指標迴圈引用而引入的智慧型指標,典型代表是boost::weak_ptr(請參見隨筆《 [6]智慧型指標boost::weak_ptr 》);

good good study, day day up.

順序  選擇  迴圈  總結

智慧型指標 2

一 指標指標能做什麼 在編寫c 程式的時候,讓我們最頭痛的問題就是記憶體洩露,也就是說 int pt new int delete pt 必須保證new和delete必須成對出現。作為程式設計師,我們最理想的指標,是可以像使用普通變數一樣來使用的指標,這個指標可以在恰當的時候被自動釋放。智慧型指標就...

筆記 2 智慧型指標

原生指標是一款很強大的工具,但是依據進數十年的經驗,可以確定的一點是 稍有不慎,這 個工具就會反噬它的使用者。c 11標準中規定了四個智慧型指標 std auto ptr,std unique ptr,std shared ptr,std weak ptr.他們都是用來輔助管理動態分配物件的宣告週期...

智慧型指標 強弱智慧型指標

在平時編寫 的時候經常會用到new來開闢空間,而我們開闢出來的空間必須得手動去delete他,但是如果程式設計師忘記去手動釋放那邊會出現乙個麻煩的問題,記憶體洩漏!或者是一塊記憶體被多個函式同時使用時,如果其中乙個函式不知道還有其他人也在使用這塊記憶體而釋放掉的話同樣也會引起程式的崩潰。引起記憶體洩...