公司C++規範學習

公司C++規範學習

語法部分

  • class和struct關鍵字的選擇:class表示被封裝的用戶自定義類型,不公開定義非靜態數據成員,struct表示數據的簡單集合,只定義用於初始化數據成員的方法。
  • 必須使用構造函數初始化列表顯示初始化直接基類與全部基類類型數據成員。
  • 沒有複製意義的類必須用DISALLOW_COPY_AND_ASSIGN宏禁止拷貝構造函數和賦值構造函數。
    • DISALLOW_COPY_AND_ASSIGN 宏就是將複製拷貝函數和賦值操做符聲明爲私有變量。
  • 禁止在構造函數中進行可能出錯的複雜操做(好比申請資源),複雜操做用額外的init()函數實現。
  • 顯式初始化可以使代碼更清晰、不易錯誤調用,還能避免二次賦值形成的效率問題, 單參構造函數儘可能加上explicit。
  • 有默認值語義的類必須顯示定義默認構造函數。
  • 沒有默認值語意的類,必須顯式定義其它構造函數或 private 聲明默認構造函數,並不給出實現。
  • 若是類型是可拷貝,必定要同時定義拷貝構造函數和賦值構造函數,若是類型可移動,必定要同時定義移動構造函數和移動賦值函數。
    • 若是使用默認的拷貝和移動操做,要使用=default定義。
    • 若是類型不須要拷貝、移動操做,要使用=delete手段禁用。
    • 向容器添加數據時,優先使用emplace開頭的接口函數。
  • 在極少的狀況下,當該類的隱式轉換頗有意義時,能夠不把單參數構造函數聲明爲顯式構造函數,但必須十分當心,並使用文檔化註釋說明。
  • 單參數構造函數若是不用explicit關鍵字修飾,則可能被編譯器用來作隱式類型轉換。
  • 有複製意義的類必須顯式給出複製構造函數,並當心指定其行爲(淺複製、深複製等)
    • 託管了資源的類,每每是沒有複製意義的。此時應當防止用戶錯誤調用而致使資源泄漏、重複釋放的後果。
    • 編譯器默認生成的複製構造函數,對指針數據成員使用淺複製策略,但這種策略經常不是程序員但願的。
  • 析構函數:
    • 若類定義了虛函數,必須定義虛析構函數。
    • 若類設計爲可被繼承的,應該定義公開的虛析構函數或保護的非虛析構函數。
    • [RULE010] (不包括結構)含有指針成員,必須顯式給出析構函數,並當心指定其行爲(是否銷燬指針,如何銷燬等).
    • 毫不容許讓異常離開析構函數。
  • 按照 public、protected、private 的順序聲明成員。按照類型、方法、數據成員的順序聲明成員, DISALLOW_COPY_AND_ASSIGN 放在 private 區段的末尾.
  • 不是很是必要的話,避免使用友元: 友元破壞了類的封裝性,增長了類之間的耦合,適宜使用友元的如容器與它的迭代器,類與涉及該類的.
  • 委派和繼承構造函數是由 C++11 引進爲了減小構造函數重複代碼而開發的兩種不一樣的特性. 經過特殊的初始化列表語法, 委派構造函數容許類的一個構造函數調用其餘的構造函數.
  • C++11強類型枚舉enum class Side
  • 被重載的虛函數經過override顯示聲明.
  • 禁止被重載的函數經過final顯示禁止.
  • Lambda表達式:
    • 不使用默認捕獲(包括&, =), 捕獲顯示寫出來.
  • 只在兩種狀況下使用右值引用, 一種是定義類型的移動操做函數時, 另外一種是定義模板函數實現完美轉發的時候. 除此以外, 不要使用右值引用.
    • 右值引用的語義比較複雜, 不恰當的使用會形成很難追查的bug.
  • 建議 include 的路徑、文件名與命名空間保持一致
  • 使用空格縮進,不使用製表符。 以 4 個空格爲單位縮進。避免超過 5 重的縮進。
  • 建議不要使用異常,除非已有項目/底層庫使用了異常, 這時候必需要catch全部異常。
  • 全部代碼應該定義在namespace中, main函數除外。
  • 禁止內聯(inline)虛函數,inline函數應該在10行之內。
  • 函數靜止使用默認參數,模板可使用默認參數。-- 默認參數是編譯期綁定的,不具備多態性。
  • 使用 auto 自動推導類型, 只能定義局部變量(返回類型後置聲明除外).
  • 禁止使用 auto_ptr. 若是須要傳遞對象, 使用std::unique_ptr明確全部權傳遞. 若是要共享全部權, 使用std::shared_ptr明確全部權共享.
  • [RULE033] 避免對浮點數進行相等或不等比較。
    • 避免使用非布爾型的變量或表達式做爲分支語句條件。
    • 做相等比較時,建議把常量或右值變量放在 == 運算符的右邊。
  • 除非用於條件編譯、跟蹤調試,或者可以顯著減小代碼量並確保可讀性的宏(如 DISALLOW_COPY_AND_ASSIGN, CFATAL_LOG etc.),不然不該使用。
  • 鼓勵使用前向聲明,以減小文件之間的依賴關係。
  • 儘量避免使用全局變量,若有必要應使用 singleton 模式代替。
    • 內部使用的全局函數/變量,必須聲明爲靜態函數、變量,不能在目標文件中出現外部可見的符號。
  • 不該在頭文件定義類/結構體類型的全局常量,以減小代碼膨脹。
  • 可能用於跨模塊間通信或者涉及存儲的枚舉值必須顯式指定值,避免版本不一致形成詭異的錯誤。
  • const 關鍵字用在類型名前面而非後面。
    • 不修改內部狀態的成員方法必須聲明爲 const
    • 返回不可修改的指針或引用必須聲明爲 const
    • 不被修改的引用/指針形參必須聲明爲 const
    • 除非保證狀態不會被修改,不該使用 const_cast 來去掉 const 屬性
  • 避免定義超過 4 KB 的局部變量數組

風格/約定

  • 必須按如下順序引用頭文件,並進行分節:.cpp 對應的頭文件(若是有, // 優先位置), C(標準)庫,C++(標準)庫,其它庫,本身項目的.h文件,每節內的include按照字母序。
  • 分行與空格:
    • 一條單獨的語句必須獨立成行。
    • 避免連續的空行。
    • 使用適當的空行來分組代碼的邏輯。
    • 左大括號不獨立,右大括號獨立成行。而且左大括號所在行進行垂直對齊。
  • 命名空間不縮進。
  • 構造函數初始化列表放在同一行或按至少八格縮進並排幾行, 若是須要換行, 把: 放在第一行。
  • 比較短的函數聲明,整個聲明佔一行;過長的函數聲明,令每一參數佔一行,而且垂直對齊, 換行後的參數至少保持 8 個空格縮進。
  • 比較短的函數調用語句,整個語句佔一行;過長的函數調用,控制折行確保每行不要超過 100 列,換行後至少額外縮進 8 個空格。
  • 空格的使用:
    • if/switch/while/for/catch 與後邊的圓括號之間加一個空格,圓括號內側與判斷表達式之間不加空格。
    • for語句圓括號內分號前不加空格,分號後加一個空格。
    • 函數調用中,函數名和圓括號之間不要加空格。
    • 類繼承與構造函數的初始化列表的冒號先後加一個空格。
    • 逗號表達式或參數列表中,逗號前不加空格,逗號後加一個空格。
    • 一元運算符先後不加空格。二元、三元表達式先後各加一個空格。
    • 成員訪問或做用域運算符先後不加空格。如:a.b, a->b, a.b, a->b, a::b。
    • 圓括號和方括號運算符先後和內部都不加空格。
  • .h 中不要定義複雜的函數, 複雜函數若是必須在頭文件中, 應該放在 .hpp 後綴的頭文件中。
  • 沒有使用到的函數參數,把參數名註釋起來, 不容許未命名參數出現。
    • :函數的參數順序,建議先安排輸入參數,再安排輸出參數。
    // 輸入參數對象類型使用const引用
    void foo(const std::string& input1, const MyClass& input2);

命名規範

  • 全局可見的,卻又沒法經過命名空間約束的標識符命名,必須以庫名做爲前綴,以免衝突。
  • 命名應當儘量有描述性,不使用非通用的縮寫(尤爲是省一個字符的縮寫如creat,usr等),不使用有歧義的縮寫,不使用任意的無心義的字符.
  • 標識符的做用域越大,命名就應該越清晰。
  • 可能使用多個單位名稱的變量(如表示時間的變量),應以單位名稱縮寫爲後綴。
  • 文件名所有用小寫字母, 中間用_間隔; 好比: this_is_my_awesome_file.cpp.
  • 單元測試文件名使用 <被測文件名> _test.h(.cpp)命名.
  • 若是是要發佈供它人使用的 lib,推薦僅暴露一個以庫名同名,或者 <庫名> _ <功能集合> .h的 api 頭文件,而後將相關頭文件 include 到這個 api 頭文件中。如:mylib.h,mylib_utils.h,mylib_api.h。
  • 使用下劃線分隔的全小寫命名法命名命名空間。
  • 命名空間名可使用縮寫,同時應保證簡短、不易衝突但同時富有意義。
  • 函數命名使用下劃線分隔的全小寫命名法。
  • 函數一般使用動詞短語命名。
  • 自定義類類型使用首字母大寫的駝峯命名法命名,通常不使用前綴。
  • 枚舉類型成員,使用全大寫蛇形命名法(即所有字母大寫,單詞間用下劃線分隔)。
  • 儘量不使用全局變量,若是必須使用,必須以g爲前綴,並且必須足夠長以免名字衝突。
  • 全局變量使用下劃線分隔的全小寫命名法命名。
  • 局部變量名使用下劃線分隔的全小寫命名法命名。
    • 假如局部變量做用域很小,能夠適當使用縮寫。
  • 全局靜態變量 s_ 做爲前綴。類靜態成員使用 s 前綴的下劃線分隔的全小寫命名法命名。
  • const 常量與枚舉常量都使用下劃線分隔的全大寫命名法命名
  • 肯定須要不一樣大小的變量,推薦使用<stdint.h>中定義的長度明確的整形類型,例如 int64_t, int32_t 等。
  • 多行註釋必須寫在被解釋內容的上方。單行註釋能夠寫在被註釋語句的上文或右方。api

  • 一行內只應聲明一個變量。
  • 局部變量應儘可能延遲到第一次使用處聲明。
  • 局部變量應在聲明處賦初值,指針類型局部變量必須在聲明處賦初值。
  • 本規範不適用於引入的公司外第三方代碼, 修改時請遵照第三方代碼自身的編碼風格。
  • 顯式或者經過宏等隱式的定義派生自第三方代碼中所申明的類,必須遵照對應第三方代碼自身的編碼風格。數組

相關文章
相關標籤/搜索