讀書筆記 |Google C++編程風格指南


讀書筆記 |Google C++編程風格指南
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語句的函數
    • 除非大多數狀況下,循環和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 存取控制

  • 即get/set函數
  • 存取函數通常內聯在頭文件中

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.思惟導圖筆記

Paste_Image.png
大圖多線程

相關文章
相關標籤/搜索