42

私は多くの最上位のヘッダーファイルで以下のマクロを見てきました:

#define NULL 0  // C++03

コード全体で、NULL0同じ意味で使用されます。に変更すると。

#define NULL nullptr  // C++11

それは悪い副作用を引き起こしますか?次の使用法は不整形になるので、私は唯一の(良い)副作用を考えることができます。

int i = NULL;
4

6 に答える 6

40

一番上のヘッダーファイルで以下のマクロを見ました:

あなたはそれを見るべきではありませんでした、標準ライブラリはそれを<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*)

しかし、それが事実であるならば、それはとにかくほぼ確実に壊れていました。

于 2012-01-25T13:28:50.610 に答える
15

コード全体を検索NULLして置き換えるのがはるかに優れています。nullptr

構文的には安全かもしれませんが、どこに置き#defineますか?コード編成の問題が発生します。

于 2012-01-25T13:26:36.550 に答える
7

いいえ。標準マクロを(再)定義することは許可されていません。そして、あなたが見るなら

#define NULL 0

標準ヘッダー以外のファイルの先頭にある場合(さらに、そこにある場合でも、インクルードガードに含まれている必要があり、通常は追加のガードにも含まれている必要があります)、そのファイルは壊れています。それを除く。

NULL優れたコンパイラは通常、次のように定義することに注意してください。

#define NULL __builtin_null

、非ポインタコンテキストで使用された場合に警告をトリガーする組み込みのコンパイラにアクセスします。

于 2012-01-25T13:42:38.117 に答える
4

<cstddef>独自のバージョンの;を作成しているのでない限り、それを定義するべきではありません。それは確かに「多くの最上位のヘッダーファイル」にあるべきではありません。

独自の標準ライブラリを実装している場合、唯一の要件は

18.2 / 3マクロNULLは、実装定義のC++nullポインター定数です。

したがって、0またははnullptr許容可能であり、nullptr指定した理由から(コンパイラがサポートしている場合)より優れています。

于 2012-01-25T13:34:41.470 に答える
4

そうでないかもしれない

オーバーロード動作の特定の形式がある場合:

void foo(int);
void foo(char*);

次に、コードの動作:

foo(NULL);

NULLがnullptrに変更されるかどうかによって変わります。

もちろん、この回答にあるようなコードを記述しても安全かどうかについては、別の質問があります...

于 2012-01-25T14:20:02.957 に答える
2

下位互換性が損なわれる可能性がありますが、新しいコードの場合、これは問題ではありません。を意味する場合は、nullptrではなく、を使用する必要があります。また、ゼロを意味する場所を使用する必要があります。NULLnullptr0

于 2012-01-25T13:29:04.557 に答える