三、例外
條款9:利用destructor避免泄露資源
把資源封裝在物件內,通常可以在exception出現時避免資源泄露
條款10:在建構式內阻止資源泄露
C++僅僅能洗掉被完全構造的物件(fully constructed objects),只有一個物件的建構式完全運行完畢,這個物件才被完全地構造,C++拒絕為沒有完成構造操作的物件呼叫解構式,
在建構式中可以使用try catch throw捕獲所有的例外,更好的解決方法是通過智能指標的方式,
如果你用對應的std::unique_ptr或者shared_ptr物件替代指標成員變數,就可以防止建構式在存在例外時發生資源泄漏,你也不用手工在解構式中釋放資源,并且你還能像以前使用非const指標一樣使用const指標,給其賦值,
條款11:禁止例外exception流出解構式destructor之外
1.可以避免terminate函式在exception傳程序的堆疊展開機制中被呼叫,
如果控制權基于exception的因素離開destructor,而此時正有另一個exception處于作用狀態,C++會呼叫terminate函式結束程式
2.可以協助確保destructor完成其所應該完成的所有事,
如果exception從destructor內拋出,而且沒有在當地被捕獲,destructor便是執行不全,僅執行到例外拋出那一點,
條款12:了解“拋出一個exception”與傳遞一個引數或呼叫一個虛函式之間的差異
函式引數和exception的傳遞方式有三種:by value,by reference,by pointer
- 拋出一個exception,不管用什么傳遞方式,這個exception總是會被復制,防止exception離開其生存空間后被銷毀導致傳遞了空的exception物件,而對于by value傳遞,甚至會復制兩次,而引數傳遞則不一定會復制副本,
- 被拋出成為exception物件被允許的型別轉換動作只有兩種:繼承架構中的類轉換,即針對base class exception而撰寫的catch子句可以處理型別為derived class的exceptions,第二種是允許從一個型別化指標(typed pointer)轉變成無型別指標(untypedpointer),所以帶有 const void* 指標的 catch 子句能捕獲任何型別的指標型別例外,
- catch 子句匹配順序總是取決于它們在程式中出現的順序,所以不要讓處理派生類例外的 catch 子句位于處理基類例外的 catch 子句后面,而呼叫虛函式時,被選中執行的是那個與物件最吻合的函式
條款13:以by reference的方式捕捉exception
catch by reference可以避免by pointer的物件洗掉問題,也可以避開by value的切割問題(派生類exception 物件被捕捉并被視為基類例外者,將失去派生成分,切割了子類可能需要的虛函式功能),
條款14:明智運用exception specifications
條款15:了解例外處理的成本
四、效率
條款16:謹記80-20法則
一個程式80%的資源用域20%的代碼,80%的執行時間花費在20%的代碼上,
條款17:考慮使用lazy evaluation(緩式評估)
以某種方式撰寫classes,使它們延緩計算,直到那些運算結果刻不容緩被迫切需要為止,可應用于:Reference Counting(參考計數)來避免非必要的物件復制、區分 operator[] 的讀和寫動作來做不同的事情、Lazy Fetching(緩式取出)來避免非必要的資料庫讀取動作、Lazy Expression Evaluation(運算式緩評估)來避免非必要的數值計算動作,
條款18:分期攤還預期的計算成本
和上一條款相反,要求超前進度的做要求以外的更多作業,
Over-eager evaluation:如果你預期你的程式常常會用到某個計算,你可以設計一份資料結構一邊能夠有效率的處理需求,
例如常用的caching快取技術,
第二種是prefetching預先取出,比如stl種vecctor動態記憶體的分配,當需要擴張時,每次分配2倍記憶體,
條款19:了解臨時物件的來源
- reference to const引數會導致有一個臨時物件被產生出來系結至該引數上,
- 任何時候只要你看到函式回傳一個物件,就會產生臨時物件(并于稍后銷毀),
條款20:協助完成回傳值優化(RVO)
有時候某些操作或者函式必然要回傳物件,就要產生臨時物件,這無法避免,比如operator*,如果一定得以by-value方式回傳物件,可以以一種特殊寫法撰寫函式,讓他回傳constructor arguments以取代物件,

此特殊的優化行為——利用函式的return點消除一個區域臨時物件,
稱為Return value optimization,
條款21:利用多載技術避免隱式型別轉換
如下:

注意:每個“多載運算子”必須獲得至少一個用戶自定義類資訊的自變數,所以最后一個多載操作是錯的,
條款22:考慮以運算子復合形式(op=)取代其獨身形式(op)
- 一般而言,符合運算子比其對應的獨身版本效率高,因為獨身版本通常必須回傳一個新物件,而我們必須因此承擔一個臨時物件的構造和析構成本,
- 如果同時提供某個運算子的復合形式和獨身形式,便允許你的客戶在效率與便利性之間做取舍,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/295919.html
標籤:C++
上一篇:C++類結構體與json相互轉換
