Google C++編程風格指南c++
## 0. 背景
每個C++程序員都知道,C++具備不少強大的語言特性,但這種強大不可避免的致使它的複雜,這種複雜會使得代碼更易於出現bug、難於閱讀和維護。
本指南的目的是經過詳細闡述在C++編碼時要怎樣寫、不要怎樣寫來規避其複雜性。這些規則可在容許代碼有效使用C++語言特性的同時使其易於管理。git
## 1. 頭文件
1.1 #define保護
#ifndef XXX_XXX_H
#define XXX_XXX_H
...
#endif //XXX_XXX_H
1.2 能依賴聲明的就不要依賴定義
使用前置聲明,儘可能少.h文件中#include的數量,防止依賴程序員
1.3 內聯函數
- 只有當函數少於10行甚至更少時,才定義爲內聯函數
- 函數聲明爲內聯,編譯器直接在調用處展開代碼,節省成本
- 析構函數不該該內聯,析構函數每每比其表面看起來要長
- 不要內聯那些包含循環、switch語句的函數
- 虛函數和遞歸函數即便被聲明爲內聯函數,實際上他不必定被執行
1.4 函數參數順序
- 輸入參數在前,輸出參數在後
- 輸入參數通常爲:值 或 常數引用
- 輸出參數通常爲: 很是數指針
- 好處:
- 提升可讀性和易維護性
- 對函數參數的堆棧空間有輕微影響
1.5 包含文件的次序
C庫 > C++庫 > 其餘庫的h > 項目內的hgithub
##2. 做用域
2.1 命名空間
2.1.1 定義
- 將全局做用域分爲不一樣的、具名的做用域
- 防止全局做用域命名衝突
2.1.2 優勢
- 提供了可嵌套的命名軸線
- 命名軸線功能距離
- project1 : : Foo
- project2 : : Foo
2.1.3 缺點
在頭文件中使用不具名的空間容易違背C++的惟必定義原則編程
2.1.4 結論:根據上下文合理使用命名空間
- .cc文件容許甚至提倡不具名命名空間
- .cc文件包含更多、更復雜的細節
- 有對其餘命名空間中類的引用
- .h不要使用不具名命名空間
2.2 嵌套類
- 不要把嵌套類定義爲public,除非他們是接口的一部分
- 最好將嵌套類的聲明置於命名空間中
2.3 非成員函數 / 靜態成員函數 / 全局函數
- 使用命名空間中的非成員函數/靜態成員函數
- 儘可能不使用全局函數
- 更好的方法是:將非、靜做爲新類的成員
- 若是單純爲了封裝,將不相干的函數放在一塊兒,那仍是用命名空間
2.4 局部變量
- 儘量置於最小做用域,最好聲明變量時就初始化
- 聲明與第一次使用位置越近越好
- for(int i = 0; i < 10; ++i)
- gcc可正確執行,其餘for循環重用第一次循環定義的i
2.5 全局變量
- class類型全局變量是被禁止的
- 內置類型的全局變量是容許的,但使用要三思
- 多線程代碼中很是數全局變量也是被禁止的
##3. C++類
3.1 構造函數的職責
- 職責:只進行沒有實際意義的初始化
- 有意義的數據用init方法實現
- 缺點:
- 不易捕獲錯誤,不能使用異常
- 操做失敗會形成對象初始化失敗,引發不肯定狀態
- 對單參數的構造函數使用C++關鍵字explicit
- 單參數構造函數必須是明確的
- 拷貝構造函數大多數狀況也要聲明explicit
例外:特地做爲其它類的透明包裝器的類
- 禁止使用拷貝構造函數和賦值操做的宏
3.2 結構體和類
僅當只有數據時使用struct,其餘一律使用class數組
3.3 繼承
- 使用組合一般比使用繼承更適宜
- 若是使用繼承,只使用公共繼承
- 全部繼承必須是public,想私有繼承的話,應採起包含基類實例的方式替代
- 若是該類有虛函數,其析構函數也應該爲虛函數
- 派生類重定義基類的虛函數時,該派生類函數夜鶯聲明爲virtual函數
3.4 多重繼承
- 應用場景:
只有至多一個基類中含有實現,其餘基類都是純接口類
- 優勢:
相比單繼承,可複用更多代碼
3.5 接口
- 需知足的條件:
- 只有純虛函數和靜態函數
- 沒有非靜態成員函數
- 沒有定義任何構造函數
- 必須爲之聲明虛析構函數
- 確保接口的全部實現可被正確銷燬
- 此時,該虛析構函數亦爲純虛函數
3.6 操做符重載
通常狀況下不要重載操做符安全
3.7 存取控制
3.8 Summary
- 不在構造函數中作太多與邏輯相關的初始化
- 編譯器默認提供的構造函數不會對變量進行初始化
- 子類重載的虛函數也要聲明virtual關鍵字
##4. 智能指針和其餘C++特性
- 智能指針安全第一,方便第二,儘量局部化
- 通常用scoped_ptr
- 任何狀況下不用auto_ptr
- 對stl容器對象,使用shared_ptr
- 引用形參加上const,不然使用指針形參
- 避免醜代碼:(*ptr)++
- 對於拷貝構造函數,const是必須的
- 函數重載的使用要清晰/易讀
- 少用缺省函數參數
- 禁止使用變長數組和alloca
- 合理使用友元
- 慎用異常
- 使用C++風格的類型轉換,除單元測試外不要使用dynamic_cast
- 能用前置自增/減,不用後置自增/減
- 前置自增效率更高,後置自增自減要對變量值i進行依次拷貝
- 若是i是迭代器或者其餘非數值類型,必定要用前置
- const能用則用,提倡const在前
- const變量/函數/參數,會爲編譯時類型檢測增長了一層保障
- 儘可能避免使用宏(c++中)
- 儘可能之內聯函數、枚舉、常量代替之
- 不要在頭文件中定義宏
- 整數用0,實數0.0,指正NULL,字符串‘\0’
- 推薦用sizeof(varname)代替sizeof(type)
- 只使用Boost中被承認的庫
5. 命名約定
- 不要隨意縮寫,除很是用約定俗成的縮寫
- 函數名可適當爲動詞,其餘命名使用名詞
- 所有大寫+下劃線: 宏/枚舉
- 全小寫+下劃線: 變量(含類變量/結構體變量)、文件、命名空間、存取函數
- 大小寫混合: 函數/類型(類/結構體/枚舉)/常量
6.思惟導圖筆記
大圖多線程