201

C の上にボルトで固定された C++ の初期の頃は、NULL は として定義されていたため、使用できませんでした(void*)0。以外のポインタに NULL を割り当てることができなかったためvoid*、役に立たなくなりました。当時は、0null ポインターに (ゼロ) を使用することが認められていました。

私は今までゼロをヌルポインタとして使い続けてきましたが、周りはどうしても を使いたがりますNULL。個人的には、既存の値に名前 ( ) を付けることのメリットはないNULLと思います。また、ポインタを真理値としてテストすることも好きなので:

if (p && !q)
  do_something();

次に、ゼロを使用する方が理にかなっています ( を使用する場合と同様に、 をNULL論理的に使用することはできません。がゼロであると仮定しない限り、p && !qを明示的に比較する必要があります。NULLNULLNULL

NULL よりもゼロ (またはその逆) を優先する客観的な理由はありますか、それともすべて個人的な好みですか?

編集: RAII と例外を使用して、ゼロ/NULL ポインターを使用することはめったにありませんが、それでも必要な場合があることを追加する必要があります (本来はそう言うつもりでした)。

4

21 に答える 21

199

これに対する Stroustrup の見解は次のとおりです。C++ Style and Technique FAQ

C++ では の定義NULLは 0 であるため、美的な違いしかありません。私はマクロを避けたいので、0 を使用します。もう 1 つの問題は、マクロがNULL0 とは異なる、および/または整数ではないと誤って信じてしまうことがあるということです。標準化前のコードでは、NULL不適切なものに定義されていた/定義されていることがあるため、回避する必要がありました/回避する必要があります。最近ではあまり一般的ではありません。

null ポインターに名前を付ける必要がある場合は、それを呼び出しますnullptr。それが C++11 で呼ばれるものです。次に、nullptrキーワードになります。

とはいえ、小さなことを気にしないでください。

于 2008-10-07T02:21:38.820 に答える
126

これに関するBjarneの見解と矛盾すると私が信じるいくつかの議論があります(そのうちの1つは比較的最近のものです)。

  1. 意図の文書化

    を使用NULLすると、その使用法を検索できます。また、コンパイラーによってポインターが解釈されているかどうかに関係なく、開発者がポインターを使用したかったことも強調されます。NULLNULL

  2. ポインタと「int」の過負荷は比較的まれです

    誰もが引用する例は次のとおりです。

     void foo(int*);
     void foo (int);
    
     void bar() {
       foo (NULL);  // Calls 'foo(int)'
     }
    

    ただし、少なくとも私の意見では、上記の問題はNULL、nullポインター定数に使用していることではありません。それはfoo()、非常に異なる種類の引数をとるオーバーロードがあることです。int他のタイプでは呼び出しがあいまいになり、有用なコンパイラ警告が生成されるため、パラメータもである必要があります。

  3. 分析ツールは今日役立つことができます!

    NULLC ++ 0xがない場合でも、ポインターに使用されていること、および0整数型に使用されていることを確認するツールが現在利用可能です。

  4. C++11には新しいstd::nullptr_tタイプがあります。

    これは、テーブルの最新の引数です。C ++ 0xの問題は積極0的に対処されており、を提供するすべての実装について、最初に行うことは次のとおりです。NULLNULL

     #define NULL  nullptr
    

    NULLではなくを使用する場合、この変更により、ほとんどまたはまったく労力をかけずに型安全性が向上します。どちらかといえば、以前使用し0ていたいくつかのバグも検出される可能性があります。今日使用している人にとっては...まあ、うまくいけば、彼らは正規表現についての十分な知識を持っています...NULL00

于 2008-10-07T09:12:13.657 に答える
47

NULL を使用します。NULL は意図を示します。それが 0 であることは重要ではない実装の詳細です。

于 2008-10-07T03:11:13.727 に答える
42

私はいつも使用します:

  • NULLポインタ用
  • '\0'文字用
  • 0.0float と double の場合

0 で問題ありません。それは意思表示の問題です。そうは言っても、私はそれについて肛門ではありません。

于 2008-10-07T03:54:24.873 に答える
34

私はずっと前に 0 を支持して NULL の使用をやめました (他のほとんどのマクロと同様に)。これを行ったのは、マクロをできるだけ避けたかったからだけでなく、C および C++ コードで NULL が過剰に使用されているように見えるためでもあります。ポインターだけでなく、値 0 が必要な場合はいつでも使用されるようです。

新しいプロジェクトでは、これをプロジェクト ヘッダーに入れます。

static const int nullptr = 0;

C++0x 準拠のコンパイラが登場したら、あとはその行を削除するだけです。これの利点は、Visual Studio が既に nullptr をキーワードとして認識し、適切に強調表示していることです。

于 2008-10-07T03:04:02.900 に答える
22
    cerr << sizeof(0) << endl;
    cerr << sizeof(NULL) << endl;
    cerr << sizeof(void*) << endl;

    ============
    On a 64-bit gcc RHEL platform you get:
    4
    8
    8
    ================

物語の教訓。ポインターを扱うときは NULL を使用する必要があります。

1)あなたの意図を宣言します(変数がポインターなのか数値型なのかを判断しようとして、すべてのコードを検索させないでください)。

2) 可変引数を期待する特定の API 呼び出しでは、NULL ポインターを使用して引数リストの終わりを示します。この場合、NULL の代わりに「0」を使用すると、問題が発生する可能性があります。64 ビット プラットフォームでは、va_arg 呼び出しは 64 ビット ポインターを必要としますが、32 ビット整数のみを渡します。他の 32 ビットをゼロにすることに頼っているように思えますか? あまり親切ではない特定のコンパイラ (Intel の icpc など) を見たことがありますが、これは実行時エラーを引き起こします。

于 2010-11-19T16:53:03.310 に答える
17

私が正しく思い出すと、私が使用したヘッダーでは NULL が別の方法で定義されています。C の場合は (void*)0 として定義され、C++ の場合は単に 0 として定義されます。コードは次のようになります。

#ifndef __cplusplus
#define NULL (void*)0
#else
#define NULL 0
#endif

個人的には、NULL 値を使用して null ポインターを表しています。これにより、整数型ではなくポインターを使用していることを明示できます。はい、内部的に NULL 値はまだ 0 ですが、そのように表されていません。

さらに、整数からブール値への自動変換に依存するのではなく、それらを明示的に比較します。

たとえば、次を使用することをお勧めします。

if (pointer_value != NULL || integer_value == 0)

それよりも:

if (pointer_value || !integer_value)

これはすべてC++ 11で修正され、nullptrの代わりに単純に使用できNULLnullptr_tそれは a の型であると言えば十分nullptrです。

于 2008-10-07T02:23:02.000 に答える
11

私はかつて、0 が有効なアドレスであり、NULL が特別な 8 進値として定義されているマシンで作業していました。そのマシン (0 != NULL) では、次のようなコード

char *p;

...

if (p) { ... }

期待どおりに動作しません。あなたは書く必要がありました

if (p != NULL) { ... }

最近では、ほとんどのコンパイラが NULL を 0 と定義していると思いますが、当時の教訓を今でも覚えています。NULL は必ずしも 0 ではないということです。

于 2008-10-07T02:22:23.263 に答える
10

標準では NULL == 0 が保証されていると思いますので、どちらでもかまいません。あなたの意図を文書化するので、私は NULL を好みます。

于 2008-10-07T02:21:38.820 に答える
10

私は通常 0 を使用します。私はマクロが好きではありません。また、使用しているサード パーティのヘッダーが NULL を何か奇妙なものとして再定義しないという保証はありません。

C++ が nullptr キーワードを取得するまでは、Scott Meyers などによって提案された nullptr オブジェクトを使用できます。

const // It is a const object...
class nullptr_t 
{
public:
    template<class T>
    operator T*() const // convertible to any type of null non-member pointer...
    { return 0; }

    template<class C, class T>
    operator T C::*() const   // or any type of null member pointer...
    { return 0; }

private:
    void operator&() const;  // Can't take address of nullptr

} nullptr = {};

詳細については、Google の「nullptr」を参照してください。

于 2009-03-31T07:30:11.910 に答える
9

0 または NULL を使用しても同じ効果があります。

ただし、それは両方とも優れたプログラミング手法であるという意味ではありません。パフォーマンスに違いがないことを考えると、不可知論的/抽象的代替手段よりも低レベル認識オプションを選択することは、プログラミングの悪い習慣です。コードの読者が思考プロセスを理解できるようにします

NULL、0、0.0、'\0'、0x00 などはすべて同じものに変換されますが、プログラム内では異なる論理エンティティです。それらはそのまま使用する必要があります。NULL はポインター、0 は数量、0x0 はビットが興味深い値などです。コンパイルするかどうかに関係なく、ポインターに '\0' を割り当てません。

一部のコミュニティでは、環境の契約を破ることによって、環境に関する深い知識を実証することを奨励していることを私は知っています。ただし、責任あるプログラマーは保守可能なコードを作成し、そのような慣行をコードから除外します。

于 2011-03-27T15:44:58.610 に答える
5

奇妙なことに、Stroustroup を含め、誰もそれについて言及していませんでした。標準と美学について多くのことを話している間、たとえば、アーキテクチャ where の可変引数リストで inを使用することが危険であることに誰も気づいていませんでした。Stroustroup のように、私は美的な理由から好みますが、型があいまいな場所で使用しないように注意する必要があります。0NULLsizeof(int) != sizeof(void*)0

于 2009-09-17T07:24:37.117 に答える
3

私はこれについてStroustrupと一緒です:-) NULLは言語の一部ではないので、0を使用することを好みます.

于 2008-10-07T02:23:06.820 に答える
3

大部分は個人的な好みですが、NULL を使用すると、オブジェクトが現在何も指していないポインターであることが明らかになるという議論をすることもできます。

void *ptr = &something;
/* lots o' code */
ptr = NULL; // more obvious that it's a pointer and not being used

IIRC では、標準では NULL を 0 にする必要はありません。したがって、<stddef.h> で定義されているものを使用することが、コンパイラにとっておそらく最適です。

引数のもう 1 つの側面は、論理比較 (bool への暗黙のキャスト) を使用するか、NULL に対する明示的なチェックを使用するかということですが、それは読みやすさにも帰着します。

于 2008-10-07T02:24:17.457 に答える
3

値が算術値ではなくポインターを表すことを意図していることを明確にするため、NULL を使用することを好みます。それがマクロであるという事実は残念ですが、非常に広く根付いているため、危険はほとんどありません (誰かが本当に骨の折れることをしない限り)。最初からキーワードにしてほしかったのですが、いかがでしょうか?

とはいえ、ポインターをそれ自体の真理値として使用しても問題はありません。NULL と同じように、根深いイディオムです。

C++09 は nullptr コンストラクトを追加しますが、これは長い間待ち望まれていたと思います。

于 2008-10-07T02:52:00.287 に答える
1

誰かが一度私に言った...私はNULLを69に再定義するつもりです。それ以来、私はそれを使用しません:P

それはあなたのコードを非常に脆弱にします。

編集:

標準のすべてが完璧というわけではありません。マクロNULLは、実装定義のC ++ nullポインター定数であり、C NULLマクロとは完全には互換性がありません。暗黙的に非表示にする型以外に、役に立たず、エラーが発生しやすいツールに変換されます。

NULLは、nullポインターとしてではなく、O/OLリテラルとして動作します。

次の例は混乱しないことを教えてください:

void foo(char *); 
void foo(int); 
foo(NULL); // calls int version instead of pointer version! 

そのすべてのために、新しい標準ではstd::nullptr_tが表示されます

新しい標準を待ちたくなく、nullptrを使用したい場合は、少なくともMeyersによって提案されたようなまともな標準を使用してください(jon.hコメントを参照)。

于 2009-08-05T16:36:53.077 に答える
1

私は常に 0 を使用します。考え抜かれた理由があるわけではありません。最初に C++ を学習したときに、0 の使用を推奨している記事を読んで、常にそのようにしてきたからです。理論的には、読みやすさに混乱の問題がある可能性がありますが、実際には、数千の工数と数百万行のコードでそのような問題に遭遇したことは一度もありません. Stroustrup が言うように、標準が nullptr になるまでは、実際には個人的な美的問題にすぎません。

于 2008-10-07T02:51:28.683 に答える
1

私は、可能な限り 0 または NULL ポインターをまったく使用しないことを主張します。

それらを使用すると、遅かれ早かれコードでセグメンテーション違反が発生します。私の経験では、これと一般的なポインターは、C++ のバグの最大の原因の 1 つです。

また、コード全体で「if-not-null」ステートメントにつながります。常に有効な状態に依存できる場合は、はるかに優れています。

ほとんどの場合、より良い代替手段があります。

于 2013-07-10T08:34:08.187 に答える
-4

ポインターを 0 に設定することは、それほど明確ではありません。特に、C++ 以外の言語を使用している場合。これには、Javascript だけでなく C も含まれます。

私は最近、次のようなコードをいくつか使用しました。

virtual void DrawTo(BITMAP *buffer) =0;

初めての純粋仮想関数。1週間魔法のジベルジャッシュだと思った。基本的に関数ポインタを a に設定しているだけだと気づいたときnull(仮想関数はほとんどの場合 C++ の関数ポインタであるため)、私は自分自身を蹴りました。

virtual void DrawTo(BITMAP *buffer) =null;

私の新しい目に適切な間隔がなければ、その野郎よりも混乱が少なかったでしょう。null実際、現在小文字の false と true を採用しているのと同じように、C++ が小文字をあまり採用していないのはなぜだろうと思っています。

于 2010-12-02T03:50:50.263 に答える