この記事のポイント

  • =default, =deleteの役割と設計意図を整理
  • レビューで自動生成制御が適切かどうかを確認する技法を解説
  • 実務コード改善例・レビュー観点を提示

C++11で導入された設計明示記法

C++11から以下が導入されました。

構文 役割
=default 自動生成明示許可
=delete 生成禁止明示

本質は「意図をコードに埋め込む設計言語」

  • 暗黙生成の黙認設計を防止
  • 明示設計文化の中核機能

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

① 自動生成任せが設計責務を曖昧化する

  • 誰がどの設計意図でコピー・代入・moveを許可したか読めない

② 意図不一致事故を事前封止できる

  • 型安全破壊を事前に排除

③ 保守時の安全性を高める

  • 拡張追加で自動生成が暴走するのを防止

④ 設計の責務をレビュー時に可視化できる

  • 実質ドキュメントとして機能

良い実装例

class FileHandle {
public:
    explicit FileHandle(int fd) : fd_(fd) {}

    FileHandle(const FileHandle&) = delete;             // コピー禁止
    FileHandle& operator=(const FileHandle&) = delete;  // 代入禁止

    FileHandle(FileHandle&&) noexcept = default;        // ムーブ許可
    FileHandle& operator=(FileHandle&&) noexcept = default;

private:
    int fd_;
};

良い設計理由

  • 所有権一意性を完全保証
  • ムーブ転送は安全許可
  • レビュー対象が意図読み取り可能

レビュー観点

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

  • コピー・代入の許可/禁止が責務設計と一致しているか
  • =default使用は理由付けされているか
  • =deleteはコピー側・代入側とも適用されているか
  • C++03残存のprivateコピー禁止記法が混在していないか
  • ムーブ専用化設計はconsistentに統一されているか

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

class Resource {
public:
    Resource() = default;
};
@Reviewer
デフォルト生成理由が説明されていません。意図が不明瞭です。

改善例

// 非所有型でデフォルト生成許可設計
class Resource {
public:
    Resource() = default;
};

ケース2: コピー片側だけ禁止

class Connection {
public:
    Connection(const Connection&) = delete;
};
@Reviewer
コピー代入演算子も禁止してください。不整合設計です。

改善例

Connection& operator=(const Connection&) = delete;

ケース3: ムーブ専用意図の記述抜け

class Socket {
public:
    explicit Socket(int fd);
    Socket(Socket&&) noexcept = default;
};
@Reviewer
ムーブ設計時もコピー禁止は必ず明示してください。

改善例

Socket(const Socket&) = delete;
Socket& operator=(const Socket&) = delete;

ケース4: delete理由の可視化欠落

class Logger {
public:
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;
};
@Reviewer
delete理由(設計責務)をコメントで補足してください。

改善例

// シングルトン設計のためコピー禁止
class Logger {
public:
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;
};

ケース5: C++03流残存

class FileHandle {
private:
    FileHandle(const FileHandle&);
    FileHandle& operator=(const FileHandle&);
};
@Reviewer
C++11以降はdelete指定に統一してください。意図がより明示的です。

改善例

class FileHandle {
public:
    FileHandle(const FileHandle&) = delete;
    FileHandle& operator=(const FileHandle&) = delete;
};

ケース6: default使わずわざわざ空実装

class Task {
public:
    Task() {}
};
@Reviewer
空実装でなく=default使用で意図明示してください。

改善例

class Task {
public:
    Task() = default;
};

「書かずに済むから使わない」ではなく、設計をコード化する意識


default/deleteレビューの設計防止効果

設計崩壊 default/deleteで防止できる理由
コピー責務曖昧化 コピー禁止明示
デフォルト生成暴走 意図的許可のみ許容
ムーブ安全性未保証 move専用許可設計
保守バグ温床化 拡張時の暴走制御

観点チェックリスト


まとめ

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

「特殊メンバ生成は設計意図を反映して明示されているか?」

  • default/deleteは設計意図の自己文書化構文
  • C++レビューの標準作法として完全明示文化を定着させる

「暗黙生成撲滅文化」こそ現代C++レビュー力の核心です。