C++ 11では、nullptr
の以前の一般的な定義にはいくつかの問題があるため、NULL
キーワードがよりタイプセーフなNULLポインター定数として追加されました。
標準委員会が新しいNULLポインター定数NULL
を呼び出さない、またはNULL
を#define
dからnullptr
?
Stephan T. Lavavej(C++標準委員会のメンバー)は、かつて talk (55:35)で次のように説明しました。
実装は#define NULL nullptr
、次のようなかなりの用途を壊すでしょう
int i = NULL;
そして明らかにそれらがたくさんあります。そのため、変更を強制できませんでした。
nullptr
はpointer typeですが、NULL
は整数になる傾向があり、オーバーロードされた関数では、整数ではなくポインタを使用していることを明確にする必要があります-これはnullptr
が便利な場合です。
したがって、あなたの質問に本当に答えるために、NULL
とnullptr
は2つの異なる目的を果たします。1つを再定義すると、おそらく既存のコードベースの多くのことが壊れます。
それに加えて、これを Bjarne StroustrupのWebサイト からチェックしてください。
NULLまたは0を使用する必要がありますか?
C++では、NULLの定義は0であるため、外観上の違いのみがあります。私はマクロを避けることを好むので、0を使用します。NULLの別の問題は、人々がそれが0や整数ではない、あるいはその両方と異なると時々誤解することです。先行標準コードでは、NULLが不適切なものに定義されている場合があったため、避ける必要がありました。最近ではあまり一般的ではありません。 nullポインターに名前を付ける必要がある場合は、nullptrと呼びます。それがC++ 11で呼ばれていることです。次に、「nullptr」がキーワードになります。
実際に標準化委員会での議論に参加することなく、それは確かに言うのは難しいですが、それはNULL
が十分に互換性がないという意味でnullptr
を使用するコードを壊すからだと思います。古いコードを壊すことは決して良い考えではありません。
NULL
はタイプセーフではありません。歴史的な理由により、キャストなしで0として定義され、コンパイラーはこの特別なゼロのポインターへのキャスト番号の警告を黙らせます。
瞬時に、次のことができます。
void* p = 0;
暗黙的なキャストなしではこれはできません:
void* p = 1234;
副作用は、他の回答で述べたように、数値として悪用される可能性があることです。
nullptr
は、ポインターに強制することでこれを改善します。これを整数に割り当てることはできません。動作が変更されたため、下位互換性のために新しい名前が作成されます。
また、nullptr
はコンパイラによって処理され、その実際の値はユーザーに公開されないことに注意してください(NULL
の場合のゼロなど)。アーキテクチャに依存する値を使用する方がはるかに簡単です、たとえば0xdeadbeef
、プログラマーのコードロジックに影響を与えません。
Nullptrを別のタイプとして定義するという決定が、バグの防止に役立つケースを示します。
次の機能を検討してください。
void foo(int);
void foo(char *);
int main()
{
foo(NULL); // oops
}
C++ 98では、上記のコードはfoo(int)関数を呼び出します。これは、NULLが0に置き換えられているためです。
しかし、foo(nullptr)を呼び出すと、正しいものを呼び出します-foo(char *)。
NULL
を呼び出さないことを選択した理由おそらく、新しいNULLポインターはキーワードであり、キーワードを#defined
にすることはできないため、NULL
を呼び出すと、Cヘッダーが含まれている可能性があります。
NULL
が#defined
からnullptr
であることを宣言しますか?標準化委員会は、NULL
を#defined
からnullptr
にすることを許可していますが、必須ではありません。
C++ 11 18.2型[support.types]/2:マクロ
NULL
は、この国際規格の実装定義のC++ nullポインター定数です。C++ 11 4.10ポインター変換[conv.ptr]/1:nullポインター定数は整数定数式( 5.19)ゼロに評価される整数型のprvalueまたは
std::nullptr_t
型のprvalue。
下位互換性はここでは問題になりません。整数の形式0
を想定するNULL
の使用は標準準拠ではありません。実装は、この種の邪悪な振る舞いを容認するためにそれをしないことを選択するかもしれません。
The nullptr
は、型の安全性と明確さのために導入されています(おそらく、NULL
を使用して非ポインター型の初期化を停止するため)。
混乱を避け、下位互換性を確保するために、NULL
(int type)はnullptr
(pointer type)に変更されません。
したがって、標準委員会の一連の考え方は、多分あいまいさを引き起こしたり、既存のコードにブレーキをかけたりすることなく、古い表記法から新しい表記法へのスムーズな移行におそらく関連しています。