17
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C++Advent Calendar 2020

Day 10

本当にあった怖いNULL

Last updated at Posted at 2020-12-10

はじめに

C++では、NULL#define NULL 0のように定義されており、本来使うべきではないところ(ポインターに関係のないところ)でも使用できてしまいます。

C++11ではNULLの様々な問題点を解消するためにnullptrキーワードが導入されました。nullptrは整数型に暗黙変換できず、より安全です。今日ではNULLは使うべきではありません。

なぜNULLは良くないのか、過去に見た事例を振り返りながら復習してみましょう。

NULL文字とNULLの混同

NULL文字('\0')とNULLポインター(NULL)は異なる概念のものですが、名前が似ているためか、混同している事例がありました。偶然にも値が一致しているので正しく動作します。

間違いの例:

char text[256];
text[0] = NULL;

修正例:

char text[256];
text[0] = '\0';

nullptrは整数型へ暗黙変換できないため、このような問題は生じません。

char text[256];
text[0] = nullptr; // エラー

文字列オブジェクトの先頭をNULLと比較している

NULL文字とNULLの混同である上に、無駄にわかりにくいコードです。

間違いの例:

const string str = ...;
if (*str.c_str() != NULL) { ... }

修正例:

const std::string str = ...;
if (!str.empty()) { ... }

0とNULLの混同

整数の0とNULLは偶然にも値が一致しますが、異なる概念のものですから混同してはいけません。

間違いの例:

double d = NULL;

修正例:

double d = 0;

nullptrは整数型へ暗黙変換できないため、このような問題は生じません。

double d = nullptr; // エラー

falseとNULLの混同

falseNULLは偶然にも値が一致しますが、異なる概念のものですから混同してはいけません。

間違いの例:

bool f() {
   ...
   return NULL;
}

修正例:

bool f() {
   ...
   return false;
}

nullptrは整数型へ暗黙変換できないため、このような問題は生じません。

bool f() {
    return nullptr; // エラー
}

コンテナをNULLで初期化している

整数0との混同ですが、異なる勘違いが背景にあるかもしれません。

間違いの例:

std::vector<int> v(NULL);

修正例:

std::vector<int> v;

nullptrは整数型へ暗黙変換できないため、このような問題は生じません。

std::vector<int> v(nullptr); // エラー

コンストラクタはexplicitにする

std::vectorでは起こりませんが、このとき呼び出されるコンストラクタがexplicitでない場合は、以下のようなコードも通ってしまいます。

MyArray arr = NULL;

暗黙変換を意図する場合を除き、1引数のコンストラクタは必ずexplicitを指定しましょう。

class MyArray{
    ...
    explicit MyArray(int){ ... }
};
MyArray a = 0; // エラー: explicitのため暗黙変換はできない
MyArray a(0);  // OK

純粋仮想関数を宣言する0とNULLの混同

どんな教科書にもおそらく載っておらず、なぜこのようなコードが書かれたのかは謎です。

間違いの例:

virtual void f() = NULL;

修正例:

virtual void f() = 0;

もちろん、nullptrであれば文法エラーとなります。

まとめ

nullptrを使いましょう。

また、こうしたミスを発見するには、NULLnullptrに置換することが効果的です。

17
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?