c++ 性能優化策略

1 關於繼承:不能否認良好的抽象設計可讓程序更清晰,代碼更看起來更好,可是她也是有損失的,在繼承體系中子類的建立會調用父類的構造函數,銷燬時會調用父類的析構函數,這種消耗會隨着繼承的深度直線上升,因此不要過分的抽象和繼承,更爲嚴重的是當多重繼承中而且有虛函數的存在時狀況更爲複雜,的確,這些問題涉及開銷,可是,多重繼承減小了編碼的負擔,同時也讓問題的解決方案更加簡潔,這固然要付出一些代價.總之,與n個基類的多重繼承層次相關的額外虛函數表有n-1個。派生類和最左邊的非虛基類共享同一個虛函數表。所以,帶有2個基類的多重繼承層次,有1個(2-1=1)基類的虛函數表和1個派生類的虛函數表(最左邊的基類與派生類共享該虛函數表),總共有2個虛函數表,若是有虛繼承的存在,會進一步增加這個過程,它是有額外的開銷的。c++

2 對象的複合:對象的複合和繼承很類似,當一個對象包含其餘對象構造時也會引發額外的構造。關於這點可能會有不少人不解,認爲這是不可避免的,舉個例子,好比你的類A中包含了類B非指針和引用對象,那麼在你構造對象a的時候會自動調用b的無參構造函數,即便你尚未用到她,用指針代替就沒有這種消耗,另外若是你的一個對象中用到數組和字符串,你是選擇string和vector仍是char* 和c系的數組呢,若是沒有用到c++stl庫提供的相關的高級用法,建議選擇後者。算法

3 構造函數:儘可能用參數列表初始化代替參數,避免值傳遞初始化。編程

4 變量延時定義:從c系轉過來的仍保留着c的習慣,在函數第一行先把全部用到的變量都定義好,可是c是沒有運行時的消耗的,對於c++時不同的,對於c++對象的構造和銷燬時有消耗的,若是有大量的對象只在某個if條件的一個分支中出現,那就會有50%的狀況這些消耗是能夠避免的。對於這點在一個類中也是同樣的,若是成員中有成員只在某個時刻能用,就用指針代替,在構造對象時初始化成空指針,避免構造時調用他的構造函數。數組

5 虛函數:虛函數的底層實現是經過一個虛函數表來實現的,所以有虛函數的類構造時必須先初始化虛函數表,函數調用時也必須先找到虛函數表,而後經過指針偏移找到相應的函數,一般狀況下調用虛函數是沒有運行時消耗的,可是根據編譯器的實現不一樣,在調用虛函數時,有些調用可能致使增長虛函數表大小的額外開銷,或者只有那些須要調整this指針的調用纔會發生額外的運行開銷,但不會增長虛函數表的大小,在多重繼承和虛基類的時候這種消耗會顯著增長,關於繼承已經提過,因此避免濫用虛函數和虛繼承,有時候能夠用模版設計來代替虛繼承,把運行時的消耗提早到編譯期。關於虛函數的消耗:點擊打開連接緩存

6 返回值優化: 雖然c++編譯器會選擇性的進行RVO優化可是不是強制的,當函數有多個返回語句而且返回不通名稱的對象,函數過於複雜,返回對象沒有定義拷貝構造函數時,rvo優化是不會執行的,因此當函數返回一個很大的對象時在不肯定rvo優化會執行時,儘可能避免值傳遞。網絡

7 變量的定義:在定義變量時儘可能避免類型的不匹配形成臨時變量的產生。多線程

8 內存管理:c++內存管理的大權由咱們本身掌握,對於項目中要頻繁申請和釋放的對象建議用簡單的內存池來管理,能夠大大的下降頻繁申請和釋放內存帶來的消耗。異步

9 善用內聯:內聯函數不只僅是簡單的函數調用似的優化,他還有一個最大的優勢就是,可讓編譯期進行進行邊界代碼的運行環境優化,內聯把代碼拷貝到執行環境處避免了函數調用帶來的消耗,而且編譯期能夠進行正常的編譯優化,而函數調用是不能實現的。函數

10 stl :記住一點stl不是惟一的選擇,有時候也不是最好的選擇,合理選擇stl善用stl算法。性能

11 緩存:對於屢次使用的計算結果及時緩存,避免重複計算。

12 延時計算:對於不關心計算結果的計算過程儘可能延時執行或者異步去執行。

13 多線程:儘量的使用無鎖式多線程開發,鎖是一個很是消耗性能的東西,保證數據同步的手段有不少,voalite,原子操做均可已實現,儘可能經過一些技巧使用這些手段避免所得使用,若是無可奈何要使用鎖,儘可能減小鎖的消耗,好比下降鎖的粒度,使用性能更高的鎖等等。

14 std::move操做: 當不得不進行深拷貝時,若是深拷貝數據源在拷貝後就不在使用,儘量的用move操做代替,或者在參數傳遞時用move操做代替臨時的實參變量。

15 cpu緩存:合理的利用cpu cache能夠極大的提升代碼的運行效率(例如:數組中以每列遍歷和每行遍歷的效率的不一樣),固然多線程環境下也要考慮cpu cache帶來的影響。

16 內存對齊:在進行網絡編程時,最好對網絡中傳送的數據快進行內存補齊,一般是8字節對其,提升cpu訪問內存效率,從而提升數據讀寫速度。

17 函數參數:用const引用代替值傳遞,若是函數參數過多,能夠用對象來打包參數,減小參數過多帶來的性能消耗。

18 算法: 儘量的優化你的算法。

19 關於智能指針:對於智能指針個人選擇是必須用,它能夠大大下降程序的crash頻率,可是智能指針的和普通指針相比是有額外的消耗的,她的底層是一個原子操做來來統計引用數和一個普通指針,雖然原子操做和鎖相比性能高了很多可是和普通的加減操做仍是慢了很多,智能指針的大小爲16個字節,而普通指針的大小隻有4個字節,拷貝的成本也不同,因此在使用正確的狀況下可使用智能指針的引用來減小拷貝的消耗(注意這裏的前提是正確的使用引用,不要引用以一個即將被銷燬的變量)。

20 內存池:對於須要頻繁申請和釋放的內存對象,若是能夠重複利用對象的內存,強烈建議經過內存池或者重載對象的new操做符或者重載對象的placement new操做符來減小頻繁的申請和釋放內存,從而減小申請和釋放內存的消耗和內存碎片的產生。

21 其餘優化方案:位運算代替乘除法,前綴運算符代替後綴運算等等。