????????本文章屬于專欄《業界Cpp進階建議整理》
????????繼續上一篇《More Effective C++》- 極精簡版 1-10條。本章我會繼續講解我對11-20條的極精簡的理解。
- 11、不要讓destructor的異常流出
- 先保障不會拋出異常,如果不能,就使用try catch,這里的注意catch里面不再拋出異常也需要人來保證
- 12、拋出一個exception VS 傳遞一個參數 VS 一個虛函數之間的差異
- 異常機制的個人見解:異常機制核心收益是減少了用戶對三方庫的理解成本。在業務代碼中使用try-catch包住異常,以讓三方庫的異常在有限的范圍內,并且業務代碼的函數執行狀態由返回值表示。如果記不住繁瑣的異常機制,記住我說的這個原則就夠了。
- 調用函數時,控制權會回到調用端,但是異常不會
- exception objects總是被復制,如果以by value捕獲,會被復制兩次
- throw 的exception對象,使用的靜態類型,而不是動態類型
- catch子句,會在第一次匹配成功時執行
- 虛函數總是找到最匹配的,而不是第一個匹配的
- 13、以by reference方式捕捉exceptions
- by point要擔心當前point是否可用
- by value有復制成本
- 14、明智使用excpetion specification
- 個人見解:這個規則已經不適合c++11及之后的版本。忘記它,考慮第12條中我給出的建議
- 15、異常處理的成本
- exception是c++的一部分,即使你從未使用,只要有一個依賴庫用了,就有了一些成本。如果不要,需要對編譯器明確禁止
- 整體try語句快,代碼膨脹5%-10%,速度下降5%-10%
- exception成本較高,但是它出現的頻率是極低的,比正常情況慢3個數量級。
- 注意,這個性能的變換,more effective cpp的作者也是根據部分測試結果來判斷的,它很難推斷,而是需要測試驗證。
- 16、80-20法則
- 用性能測試工具找到性能瓶頸,然后花80%的精力優化20%
- 17、緩式評估
- 寫時復制,如String s1 = "a"; String b = "a",編譯器可能會只有在b使用時,才進行真正的復制。這也是變量定義貼近使用句子的道理
- 區分讀寫,cout << a[0]為讀,a[0] = 'a'為寫。operator并不能區分,但是通過proxy class可以做到(30條)
- 個人見解:核心思想是,等到確定真正要用的時候才做計算。它并不能減少需要計算數據的計算量,而是盡量不做不需要結果的計算
- 如矩陣的class operator* 并不是真正的相乘,而是記錄所需信息。而是在operator[],才真正的做計算
- 18、分期攤還預期的計算成本
- 當預期部分數據被頻繁需要時,提前計算。如vector每次預分配的內存,是當前的兩倍
- 19、了解臨時對象的來源
- 臨時變量不是局部變量,臨時變量并沒有名字
- 兩種來源:隱式轉換作為函數參數、函數返回對象時
- char* a = (str_ + "end").c_str(); a指向了一個臨時對象(注意不是局部變量),隨時可能改變
- 20、協助完成“返回值優化”
- 個人見解:在現代C++中,函數返回對象時,編譯器會先嘗試使用RVO,不行會先考慮使用移動構造函數,最后才是拷貝構造函數。所以,對于c++的默認對象或者小對象,直接返回,編譯器會幫助用戶只拷貝一次,對于大的對象建議還是在棧上申請,通過指針傳遞