私は多くの最上位のヘッダーファイルで以下のマクロを見てきました:
#define NULL 0 // C++03
コード全体で、NULL
は0
同じ意味で使用されます。に変更すると。
#define NULL nullptr // C++11
それは悪い副作用を引き起こしますか?次の使用法は不整形になるので、私は唯一の(良い)副作用を考えることができます。
int i = NULL;
一番上のヘッダーファイルで以下のマクロを見ました:
あなたはそれを見るべきではありませんでした、標準ライブラリはそれを<cstddef>
(と<stddef.h>
)で定義しています。また、IIRCは、標準に従って、標準ヘッダーファイルで定義された名前を再定義すると、未定義の動作が発生します。したがって、純粋に標準的な観点からは、そうすべきではありません。
私は人々が次のことをしているのを見てきました、何らかの理由で彼らの壊れた心は考えました:
struct X{
virtual void f() = NULL;
}
([誤って]のように: "仮想テーブルポインタをNULL
"に設定します)
NULL
これは、がとして定義されている場合にのみ有効です。これは、が純粋仮想関数の有効なトークンであるためです(0
)。= 0
§9.2 [class.mem]
とは言うものの、nullポインター定数として正しく使用されていれば、何も壊れてはなりません。NULL
ただし、正しく使用されているように見えても、これは変更されることに注意してください。
void f(int){}
void f(char*){}
f(0); // calls f(int)
f(nullptr); // calls f(char*)
しかし、それが事実であるならば、それはとにかくほぼ確実に壊れていました。
コード全体を検索NULL
して置き換えるのがはるかに優れています。nullptr
構文的には安全かもしれませんが、どこに置き#define
ますか?コード編成の問題が発生します。
いいえ。標準マクロを(再)定義することは許可されていません。そして、あなたが見るなら
#define NULL 0
標準ヘッダー以外のファイルの先頭にある場合(さらに、そこにある場合でも、インクルードガードに含まれている必要があり、通常は追加のガードにも含まれている必要があります)、そのファイルは壊れています。それを除く。
NULL
優れたコンパイラは通常、次のように定義することに注意してください。
#define NULL __builtin_null
、非ポインタコンテキストで使用された場合に警告をトリガーする組み込みのコンパイラにアクセスします。
<cstddef>
独自のバージョンの;を作成しているのでない限り、それを定義するべきではありません。それは確かに「多くの最上位のヘッダーファイル」にあるべきではありません。
独自の標準ライブラリを実装している場合、唯一の要件は
18.2 / 3マクロNULLは、実装定義のC++nullポインター定数です。
したがって、0
またははnullptr
許容可能であり、nullptr
指定した理由から(コンパイラがサポートしている場合)より優れています。
そうでないかもしれない
オーバーロード動作の特定の形式がある場合:
void foo(int);
void foo(char*);
次に、コードの動作:
foo(NULL);
NULLがnullptrに変更されるかどうかによって変わります。
もちろん、この回答にあるようなコードを記述しても安全かどうかについては、別の質問があります...
下位互換性が損なわれる可能性がありますが、新しいコードの場合、これは問題ではありません。を意味する場合は、nullptr
ではなく、を使用する必要があります。また、ゼロを意味する場所を使用する必要があります。NULL
nullptr
0