この記事のポイント

  • メンバー初期化リストの原則と漏れやすい危険性を整理
  • レビューで安全性・性能・責務意図を確認する具体技法を解説
  • 実務コードの改善例・レビュー観点を提示

C++におけるメンバー初期化リストの役割

C++ではコンストラクタ内でメンバーを次の2通りで初期化可能です。

初期化方法 記法 説明
メンバー初期化リスト : member(value) 正統派
コンストラクタ本体代入 { member = value; } 代入

レビューで重要なのは以下

初期化は初期化リストで行うのが設計の基本である


なぜレビュー対象になるのか

① 値の二重代入が発生しやすい

  • 代入式はデフォルト初期化 → 再代入の冗長

② constメンバーが代入不能

  • 初期化リスト以外では代入できない

③ 参照型メンバーも初期化リスト必須

④ 順序依存の事故が起きやすい

  • メンバー定義順に依存する初期化

⑤ 保守時に意図読み取り負荷が上昇

  • メンバー初期化状態が散在

初期化リストの原則

メンバー種別 レビュー判断
値型 初期化リスト推奨
const 必須
参照型 必須
ポインタ型 原則推奨(明示性維持)

良い実装例

class User {
public:
    User(int id, const std::string& name)
        : id_(id), name_(name) {}

private:
    int id_;
    std::string name_;
};

良い設計理由

  • 一貫して初期化リスト使用
  • const安全性保証
  • 意図読み取り容易

レビュー観点

レビューアーは以下を確認する。

  • 全メンバーが初期化リストで初期化されているか
  • const・参照型は必ず初期化リスト使用されているか
  • デフォルト→代入の冗長処理が残存していないか
  • 初期化順序に潜在事故が含まれていないか
  • 初期化責務がコンストラクタ本体に漏れていないか

良くない実装例: ケース1

class User {
public:
    User(int id, const std::string& name) {
        id_ = id;
        name_ = name;
    }

private:
    int id_;
    std::string name_;
};
@Reviewer
初期化リストを使用してください。無駄な二重代入が発生しています。

改善例

User(int id, const std::string& name)
    : id_(id), name_(name) {}

ケース2: constメンバーに代入式適用

class Config {
public:
    Config(int timeout) {
        timeout_ = timeout;
    }

private:
    const int timeout_;
};
@Reviewer
constメンバーは初期化リスト必須です。代入は成立しません。

改善例

Config(int timeout)
    : timeout_(timeout) {}

ケース3: 参照型の初期化漏れ

class Manager {
public:
    Manager(Database& db) {
        db_ = db;
    }

private:
    Database& db_;
};
@Reviewer
参照型は初期化リストが必須です。代入は無効です。

改善例

Manager(Database& db)
    : db_(db) {}

ケース4: 定義順と異なる初期化順序

class Pair {
public:
    Pair(int a, int b)
        : second(b), first(a) {}

private:
    int first;
    int second;
};
@Reviewer
初期化順序は定義順に従います。順序誤解を防ぐため記述順を揃えてください。

改善例

Pair(int a, int b)
    : first(a), second(b) {}

ケース5: defaultメンバ初期化逃避

class User {
public:
    User(int id) : id_(id) {}

private:
    int id_;
    std::string name_ = "unknown";
};
@Reviewer
default member initializerはコンストラクタ全体設計の整合性をレビュー確認してください。

改善例

User(int id, const std::string& name = "unknown")
    : id_(id), name_(name) {}

ケース6: メンバー初期化の責務散在

class Session {
public:
    Session() {}

    void init(int id, const std::string& token) {
        id_ = id;
        token_ = token;
    }

private:
    int id_;
    std::string token_;
};
@Reviewer
初期化責務はコンストラクタ集中設計を推奨します。

改善例

Session(int id, const std::string& token)
    : id_(id), token_(token) {}

メンバー初期化リストレビューの設計意義

防止対象 設計効果
二重代入 初期化効率最適化
const初期化漏れ 型安全性維持
参照初期化漏れ コンパイル保証
順序誤読 初期化整合性可視化
責務散在 設計集中管理

観点チェックリスト


まとめ

レビューアーが常に確認すべき判断基準は:

「本当に初期化リストに集約できているか?」

  • 初期化は代入ではない
  • 初期化リスト文化が型安全設計文化の中核

「責務集中型初期化レビュー」こそC++レビュー育成の基本スキルです。