《Effective C++》閱讀總結(三):資源管理

zq發表於2022-05-29

C++中的資源管理非常重要,在將資源載入到記憶體後,便可以使用資源了,當我們不再需要資源時,我們要保證其正確的釋放,才能將其佔用的記憶體空間歸還給作業系統,不正確的釋放很容易造成記憶體洩漏。本章以資源管理類為基礎,提出了以下幾條準則,這章內容比較簡單,大概總結一下:

13. 以物件管理資源

絕大多數資源都是動態分配於堆記憶體之中,然後被用於某個區域性範圍區域內。這類資源應該在控制流離開該區域時被釋放,或者全域性資源在退出main函式時也應該釋放。通常我們用new建立一個堆物件,最在使用完物件後用delete完成銷燬釋放,在建立後銷燬前期間,如果發生函式提前退出或者物件指標被重置,則相應的堆記憶體就無法釋放了。智慧指標是一種指標管理類,它可以執行幾乎所有裸指標能執行的操作,而且智慧指標在離開作用域時會自動呼叫所指物件的解構函式,所以用智慧指標物件來管理資源的指標是一個非常好的選擇。一個很簡明的原則就是:資源獲取時便進行初始化————RAII。即一個獲取的資源在獲得時就應該被放進資源管理類(智慧指標)中,並在資源管理類析構的時候完成資源釋放。例如:std::shared_ptr<OneClass> p_oneclass(new OneClass(666)),這種寫法能夠保證在適當的時候正確釋放物件。
PS:當然,無腦使用智慧指標也不好,在除錯程式碼的時候,無法直接看到智慧指標所指物件的成員狀態,不利於修bug。

14. 在資源管理類中小心copy行為

如果需要複製RAII物件,那麼也請完全複製其管理的資源,但資源我們一般都是讀取,所以更好的選擇是抑制copy行為,在copy時實施引用計數,當引用計數為0時,執行析構釋放資源。總之就是使用std::shared_ptr管理物件。

15. 在資源管理類中提供對原始資源的訪問

這是為了適配需要訪問原始資源的介面,所以智慧指標提供了一個.get()介面返回其管理的裸指標。但需要明確的是,獲取的裸指標只用來訪問資源,不應對該指標執行delete,因為釋放操作是授權給智慧指標的。多次釋放會導致非法釋放記憶體錯誤。

16. 成對的使用new和delete時,要採用相同的形式

這個很簡單,即構造一個物件,呼叫new構造,呼叫delete釋放。構造物件陣列,呼叫new Array[]構造,呼叫delete[] Array釋放。

17. 以獨立語句將newed物件置入智慧指標

① 智慧指標的建構函式是explicit的,即不會對輸入引數進行隱式轉換;
還是為了防止記憶體洩漏,以獨立語句將newed物件置入智慧指標,即std::shared_ptr<OneClass> p_oneclass(new OneClass(666))單獨一行。因為如果這樣使用int ret = Fun(std::shared_ptr<OneClass>(new OneClass(666)), other_func()), 編譯器有可能將other_func()的執行放在new完物件和構造智慧指標物件之間,如果此時other_func()丟擲異常,那麼指向資源的指標會丟失,造成記憶體洩漏。

小結:將你不知道該何時釋放的物件放入智慧指標管理。

相關文章