Google C++ Style Guide要約(一部)

4 min read読了の目安(約3700字

「Google C++ スタイルガイド 日本語全訳」のメモ

https://ttsuki.github.io/styleguide/cppguide.ja.html

ネーミングルール(命名規則)

  • 全般
    • 名前の分かり易さ > 短い名前
    • 省略形は広く一般に知られたもののみにする(具体的にはWikipediaレベル)
  • 一覧表
要素 つづり方 記号
変数名 小文字 _ table_name, tablename
クラスのメンバ名 小文字、最後に _ をつける _ table_name_
定数名(静的変数、グローバル変数)/列挙型のメンバ 最初に k をつける、区切りごとに大文字 _ kAndroid8_0_0
定数名(ローカル変数など上記以外) 小文字 _ table_name, tablename
定義値 すべて大文字 _ PI_ROUNDED
関数名/クラス名/列挙型の名前 大文字始まり、区切りごとに大文字 なし AddTableEntry
ファイル名 すべて小文字 _ または - my_useful_class.cpp
型名 大文字始まり、区切りごとに大文字 なし UrlTable

スペース位置と改行

  • スペースが1つ必要
    • 閉じ丸カッコと開き波カッコの間:) {
    • コロンの前後:for (auto : counts)
      • case文は除く
  • スペースは不要
    • 関数名と開き丸カッコの間:func(
    • 開き丸カッコと変数の間:(int a
    • テンプレートの<>の中:<int>
    • ピリオド、アロー演算子の周り:a.b, a->c
    • ポインタ演算子と変数名との間:&x, *y
      • 変数、引数をポインタとして宣言するときはどちらにつけていい:char *c, char* c
    • セミコロンの前:... = 0;
    • 波かっこでの初期化リストの内側:{1, 2}
  • 改行しない(改行マークを\nで示す)
    • 開き丸カッコは常に関数名と同じ行に書く:func(\n
    • 開き波カッコは常に関数宣言の最後に書く:...) {\n
    • 閉じ波カッコは、それ自身で最後とするか、開き波カッコと同じ行に書くかのいずれか:}\n or {...}
    • ファイルの行末(マージ時の余計な手間をなくす)
int func<int>(int a, ...) {

変数

ローカル変数

関数内で宣言するとき

  • スコープはできるだけ狭くする
    =使う直前に宣言する(Cとは異なるので注意)
    • ループ内でオブジェクトを宣言する場合は、ループの直前でもいい
      理由: ループのたびにコンストラクタが呼び出され、性能が落ちるから
  • 宣言と同時に初期化する(1行で)
    • ※for文などの直前で宣言した場合は初期化しなくてもいい

定数 (const 修飾子)

  • 変数が変更されないことを示すときは、常に使うこと
  • const の位置は型名より前。例: const int foo
  • const な変数を関数へ渡すときは、関数の引数も const でないといけない

キャスト

C言語形式のキャストは使ってはいけない

double d = 3.14;
// int i = (int) d;  // NG
int i = static_cast<int>(d);  // OK

関数

関数の実装

  • 要点をしぼる
  • 行数は少なく。目安は40行程度

関数呼び出し

  • 引数へ渡す値が複雑な式で1行が長くなるとき
    • 一時変数を作ってそこに代入したのを代わりの引数にしていい
      ※ちゃんとした名前にすること
  • 改行する場合は下記のどちらか
    • 後続の行は最初の引数にそろえる
    • スペース4つでインデントした後続行に、引数を書く
bool result = DoSomething(averyveryveryverylongargument1,
                          argument2, argument3);

bool result = DoSomethingDoSomethingDoSomething(
    argument1, argument2,  // スペース4つでインデント
    argument3, argument4);

クラス

クラスのフォーマット

  • public:, protected:, private:
    • インデントはスペース1つ
    • に空行を入れる
    • に空行を入れない
class MyClass : public OtherClass {
 public:  // インデントはスペース1つ
  MyClass();
  // 省略

  // ↓空行を入れる

 protected:
  void SomeFunction();  // ←protectedとの間に空行禁止
  // 省略

 private:
  bool SomeInternalFunction();

  int some_var_;
  int some_other_var_;
};

宣言順

  1. 型(typedef、using、内部構造体・クラスを含む)
  2. 定数
  3. ファクトリ関数
  4. コンストラクタ
  5. 代入演算子
  6. デストラクタ
  7. それ以外のすべてのメソッド
  8. データメンバ

条件文

if文については特に気を付けることはない。

if (xxx) {  // スペースを入れる
  xxx;  // インデントはスペース2つ
}

switch文

インデントと中括弧

switch (var) {
  case 0: {  // スペース2つでインデント
    ...      // スペース4つでインデント
    break;
  } // ←複数行の場合、中括弧が必要
  case 1: {
    // 何もしない場合も中括弧が必要
  }

ループ

ループ内でしか使わない変数は、()内で宣言する。
複数ある場合はループに入る直前に宣言していい。

for (int i = 0; ...; ++i) {

列挙型

ネーミングルール以外は気を付けることはない

/**
 * @brief 比較結果
 */
typedef enum {
  kDifference,  ///< 差分あり
  kNoDifference,  ///< 差分なし
  kInvalid,  ///< 無効な値
} ComparisonResult;

auto

  • autoを使うとき
    • 型の名前が長いとき
      • イテレータやそのほかの長い型名、特にfindやbegin、endの呼び出し時など
    • 型の名前が明確
    • 型の名前が重要でない(=型の名前がコードを読む人の理解の役に立たない場合)
  • autoを使わないとき: 型名を明示することで可読性が向上する場合

コメント

  • 形式
    • ///* .. */ どちらを使ってもOK. ただし、一貫性を持つこと。
    • 行末コメントを入れる場合、コードとの間に2つのスペースを入れる。
  • 冗長なコメントは書かない
    • コメントなしの具体的な変数名 > コメントありの曖昧な変数名
    • 分かっていることをいちいちコメントに書かない
  • コメントを書くべき箇所
    • トリッキーなことをする処理
    • 複雑な処理
    • 明らかでない内容

禁止事項

  • マクロをヘッダで定義する×
  • using の使用を極力禁止
    using ::testing::ほげほげ;  // NG
    
  • std::auto_ptr ではなく std::unique_ptr を使うこと

その他

  • インクリメント/デクリメント
    • (前置でも後置でも結果が変わらない場合) 前置の形を使用する。つまり ++i