web-dev-qa-db-ja.com

nullptr NULLを呼び出さないのはなぜですか?

C++ 11では、nullptrの以前の一般的な定義にはいくつかの問題があるため、NULLキーワードがよりタイプセーフなNULLポインター定数として追加されました。

標準委員会が新しいNULLポインター定数NULLを呼び出さない、またはNULL#definedからnullptr

66
immibis

Stephan T. Lavavej(C++標準委員会のメンバー)は、かつて talk (55:35)で次のように説明しました。

実装は#define NULL nullptr、次のようなかなりの用途を壊すでしょう

int i = NULL;

そして明らかにそれらがたくさんあります。そのため、変更を強制できませんでした。

70
Baum mit Augen

nullptrpointer typeですが、NULLは整数になる傾向があり、オーバーロードされた関数では、整数ではなくポインタを使用していることを明確にする必要があります-これはnullptrが便利な場合です。

したがって、あなたの質問に本当に答えるために、NULLnullptrは2つの異なる目的を果たします。1つを再定義すると、おそらく既存のコードベースの多くのことが壊れます。

それに加えて、これを Bjarne StroustrupのWebサイト からチェックしてください。

NULLまたは0を使用する必要がありますか?

C++では、NULLの定義は0であるため、外観上の違いのみがあります。私はマクロを避けることを好むので、0を使用します。NULLの別の問題は、人々がそれが0や整数ではない、あるいはその両方と異なると時々誤解することです。先行標準コードでは、NULLが不適切なものに定義されている場合があったため、避ける必要がありました。最近ではあまり一般的ではありません。 nullポインターに名前を付ける必要がある場合は、nullptrと呼びます。それがC++ 11で呼ばれていることです。次に、「nullptr」がキーワードになります。

41
Kiloreux

実際に標準化委員会での議論に参加することなく、それは確かに言うのは難しいですが、それはNULLが十分に互換性がないという意味でnullptrを使用するコードを壊すからだと思います。古いコードを壊すことは決して良い考えではありません。

8
Mats Petersson

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 *)

2
Minas Mina

標準委員会が新しいNULLポインター定数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]/1nullポインター定数は整数定数式( 5.19)ゼロに評価される整数型のprvalueまたはstd::nullptr_t型のprvalue。

下位互換性はここでは問題になりません。整数の形式0を想定するNULLの使用は標準準拠ではありません。実装は、この種の邪悪な振る舞いを容認するためにそれをしないことを選択するかもしれません。

2
K-ballo

The nullptrは、型の安全性と明確さのために導入されています(おそらく、NULLを使用して非ポインター型の初期化を停止するため)。

混乱を避け、下位互換性を確保するために、NULL(int type)はnullptr(pointer type)に変更されません。

したがって、標準委員会の一連の考え方は、多分あいまいさを引き起こしたり、既存のコードにブレーキをかけたりすることなく、古い表記法から新しい表記法へのスムーズな移行におそらく関連しています。

1
Ziezi