(Item 13 15) 以物件管理資源

2021-08-01 21:31:08 字數 2512 閱讀 1860

在以前的c++用法中,new是非常常見的用來動態分配記憶體的方式,但是有new必須有delete,將記憶體還給系統,否則就會造成記憶體洩露,這是很危險的一件事情,而以物件管理資源這一思想就能比較好的解決這一問題

通常情況下,對於乙個物件,如果是built-in型別,我們就直接new了,如果是自定義型別,一般使用工廠函式返回其指標,生成物件之後肯定需要釋放物件吧,對於內建型別,就是成對的使用delete,但是程式複雜之後,這其實是很難做到的,對於自定義型別,一般的做法就是另定義乙個函式,在這個」釋放者函式」內delete相關資源,但是也很容易產生問題——如果在delete之前,函式就return了呢?或者就continue了呢?還是會記憶體洩漏。

把資源放進物件就可以很好的避免這個問題,封裝入物件,在物件層面對其進行操作,則在資源需要釋放的時候,就會自動呼叫析構函式,而不需要我們如履薄冰一般的手動delete了,這裡還提到一種叫做raii(resource acquisition is initialization)的原則,即獲得這個物件時立刻將其置入管理資源的類中。

c++11以前有乙個auto_ptr指標,但是已經被棄用了所以不推薦,如果只打算乙個指標管理乙個物件,那麼使用unique_ptr就行了,否則用shared_ptr,要時刻注意的是,智慧型指標雖叫智慧型指標,其實質是乙個模板類,如果要用智慧型指標重寫之前的以指標傳遞的函式,則要使用.get()成員函式獲得原始指標。

class before

...lock(type* item);

...//用shared_ptr重寫

class before

...lock(type* item.get())

注意unique_ptr指標不能傳遞物件,即不能複製。

因此引出——在資源管理類中小心coping行為

如果是複製對於設計者來說是個敏感操作,那麼首先可以考慮禁用複製建構函式/賦值操作符,使用之前說過的=delete方法,如果確實複製操作,則可以考慮使用shared_ptr的引用計數,只是要注意智慧型指標當引用計數為0的時候,呼叫刪除器,物件是被銷毀的,如果不希望物件是被銷毀的操作,那麼需要我們自行傳遞乙個deleter,覆蓋預設的刪除器,可以參考另一篇部落格,只是強調:

①:shared_ptr的傳遞刪除器(deleter)方式比較簡單, 只需要在引數中新增具體的刪除器函式名, 即可; 注意是單引數函式;

②:unique_ptr的刪除器是函式模板(function template), 所以需要在模板型別傳遞刪除器的型別(即函式指標(function pointer)), 再在引數中新增具體刪除器,部落格:

智慧型指標自定義刪除器

還有不能忽略的是,管理資源的類拷貝時,往往要複製最底層的資源,所以應該是深拷貝!!!!!!

在實際使用的過程中,雖然使用資源管理類封裝了我們的物件,但是還是免不了要訪問其原始資源,這就需要我們的資源管理類提供對原始資源的訪問了。

就像前面說的,shared_ptr有乙個get()成員函式,可以返回被管理物件的原始指標,除此之外,shared_ptrunique_ptr都過載了->*操作符,我們可以向使用普通的指標一樣的操作被管理類而不用改變編碼習慣,這也是標準庫中這樣的智慧型指標被稱之為指標的原因吧,畢竟它們的使用非常接近傳統的指標。

//最好使用make_shared函式初始化智慧型指標

std::shared_ptr

i=std::make_shared(createinstance);

//可以像這樣使用

...i->memfunc();

...(*i).getitem();

所以當我們設計自己的資源管理類而不是使用標準庫版本的時候,我們也可以採用類似的做法,比如設計乙個get()介面函式,返回我們的原始資源,當然如果你想要更省力的話,可以使用隱式轉換函式,但是為了避免隱式轉換的濫用,還是建議使用設計get()函式,顯式轉換更安全。

最後需要注意的是,同時也是oop程式設計的原則之一——不要破壞封裝性,不需要/不希望提供給類使用者的細節都應該隱藏起來,在這裡需要訪問/獲得原始資料的部分,則通過介面函式提供給使用者。

條款13 以物件管理資源

問題 解決 智慧型指標。把資源放入物件內,利用析構函式確保釋放。1 資源取得時機便是初始化時機 resource acquisition is initialization raii 2 管理物件運用析構函式確保資源被釋放。別讓auto ptr同時指向同一物件。為了預防這個問題,能過copy建構函式...

條款13 以物件管理資源

我們都知道,當new乙個東西之後,必須delete它。但是問題可能出現在在new和delete之間 比如中間出現了異常,或者return之類的。一種比較好的作法是通過物件來管理 因為當物件的宣告週期結束以後,會呼叫析構函式,而在析構函式中delete,這樣的作法就靠譜多了。在標準c 中,定義了2種管...

條款13 以物件管理資源

一 如下 假設各種子型別繼承 root class investmen class investment investment createinevstment factory函式 void f 在 區域內乙個過早return,或者期間丟擲異常,流程控制不可能經過這條語句,所以這樣的話就會導致資源洩...