C++のヌルポインタはnullptrで統一すべき理由|レビューで必ず確認したい設計原則
この記事のポイント
- 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統一
- 型安全性が保証され、読み手も迷わない
レビュー観点
レビューアーは以下を確認します。
0
、NULL
表記が残っていないか- すべて
nullptr
統一できているか - 外部ライブラリAPI呼び出しでも内部でnullptr統一しているか
- マクロ依存の
NULL
定義がプロジェクトに存在していないか - 意図しないオーバーロード曖昧性が残っていないか
良くない実装例: ケース1
悪い例:NULL使用残存
ApiRequestLog* log = NULL;
process(log);
@ReviewerNULLではなく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使用はプロの最低ラインと言っても過言ではありません。