この記事のポイント

  • nullptr統一がなぜ必須なのかを整理
  • レビューでNULL/0使用をどう指摘すべきか解説
  • 実務コードでの改善例・レビュー観点を提示

ヌルポインタ表記が混在するC++の歴史的経緯

C++は長らく以下3種類の「ヌルポインタ表現」が混在してきました。

記法 説明 問題点
0 整数リテラル 暗黙型変換バグ
NULL #define NULL 0 マクロ起源で型安全性なし
nullptr C++11導入の型安全なヌル 型安全性が高い

C++11以前のコードにはNULL/0が混在する理由

  • C言語互換性維持
  • C++03以前にnullptrが存在しなかった

現在のC++(11以降)ではnullptr統一が完全に推奨される状況となっています。


なぜnullptr統一がレビュー必須なのか

① 型安全性が圧倒的に向上する

  • nullptrは専用のstd::nullptr_t型を持つ
  • 整数型・ポインタ型間の意図しない型変換を防止
void func(int);
void func(char*);

func(0);        // int優先:意図不明
func(NULL);     // int優先の可能性
func(nullptr);  // char*優先:明確

② オーバーロード解決が安全になる

  • 関数オーバーロード時の曖昧さを解消

③ マクロ定義依存がなくなる

  • #define NULL依存から脱却

④ 静的解析ツールの精度が上がる

  • ヌルポインタ解析が正確になる

良い実装例

良い例:nullptr統一
#include <memory>

class ApiRequestLog {};

void process(ApiRequestLog* log);

void example() {
    ApiRequestLog* log = nullptr;
    process(log);
}

良い設計の理由

  • 代入・初期化・引数渡しすべてnullptr統一
  • 型安全性が保証され、読み手も迷わない

レビュー観点

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

  • 0NULL表記が残っていないか
  • すべてnullptr統一できているか
  • 外部ライブラリAPI呼び出しでも内部でnullptr統一しているか
  • マクロ依存のNULL定義がプロジェクトに存在していないか
  • 意図しないオーバーロード曖昧性が残っていないか

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

悪い例:NULL使用残存
ApiRequestLog* log = NULL;
process(log);
@Reviewer
NULLではなくnullptrを使用してください。型安全性が損なわれます。
@Reviewer
既存コードに残るNULLはすべてnullptrに置き換えてください。

問題点解説

  • C言語由来の書き方が残存
  • 型安全性なし
  • 読者に「古いコード」の印象を与える

改善例

改善例:nullptrへ置換
ApiRequestLog* log = nullptr;
process(log);

レビューアーは「見つけたら必ず指摘」

  • NULL使用は残置を許容せず全廃統一が基本

ケース2: 0によるヌル表現

悪い例:0をヌル代入に使用
ApiRequestLog* log = 0;
process(log);
@Reviewer
ヌルポインタ代入に整数リテラル0は使用禁止です。nullptrへ修正してください。

問題点解説

  • 0は整数 → ポインタ代入は暗黙型変換
  • 意図が読者に伝わりにくい

改善例

改善例:nullptr使用
ApiRequestLog* log = nullptr;
process(log);

ケース3: 関数引数デフォルト値での混在

悪い例:引数デフォルト値にNULL
void process(ApiRequestLog* log = NULL);
@Reviewer
デフォルト値にもnullptr統一を徹底してください。NULL残存は曖昧な型解決を招きます。

改善例

改善例:デフォルト値にもnullptr
void process(ApiRequestLog* log = nullptr);

デフォルト値ほどnullptr統一が効く

  • ヌル初期化の意図が誰にでも明確に伝わる

ケース4: 外部ライブラリ経由の混在残存

悪い例:外部ヘッダ由来のNULL残存
#define NULL 0

ApiRequestLog* log = NULL;
@Reviewer
プロジェクト内部コードではマクロNULL使用は全廃統一が基本です。
@Reviewer
外部ライブラリが古いNULL依存でも自プロジェクト内コードではnullptr使用統一を維持してください。

改善例

改善例:外部NULLはラッピング
ApiRequestLog* log = nullptr;

ライブラリ互換性維持は型安全性を犠牲にしない

  • APIラッパー層でnullptr統一を貫くのが実務パターン

ケース5: nullptrが有効になる場面の可読性

改善例:nullptrを使うことで意図明示
void process(ApiRequestLog* log);

process(nullptr);  // 明示的に「渡さない」意図

nullptrは「意図表現子」にもなる

  • 0/NULLではなく、明示的に「ポインタ無効」を表現

観点チェックリスト


まとめ

C++レビューの基本原則として:

  • NULLは許さない
  • 0も許さない
  • nullptrだけを使う

レビューアーは「nullptr統一は自動化できる品質施策」と認識し、機械変換も含めて積極導入を推奨できます。

C++11以降の現代C++では、nullptr使用はプロの最低ラインと言っても過言ではありません。