web-dev-qa-db-ja.com

C ++のNULLと__nullの違いは何ですか?

私は次のコードを持っています:

MyType x = NULL;

NetBeansは、これをこれに変更するよう提案しました。

MyType x = __null;

調べてみると、__nullが「コンパイラー・キーワード」と呼ばれていることがわかりました。これは、コンパイラーの内部で使用されることを意味すると考えられます。 NetBeansがそれをコンパイラキーワードに変更することを提案した理由がわかりません。

C++のNULL__nullの違いは何ですか?

__nullg++内部のもので、C++ 11で追加された標準のnullptrとほぼ同じ目的を果たします(一貫してポインターとして機能し、整数ではありません)。

NULL0として定義されます。これは、整数、ブール、浮動小数点値、またはポインターとして暗黙的に使用できます。これは、ポインターを受け取る関数を呼び出すときに、オーバーロード解決の問題です。

いずれにせよ、__null実装の詳細であるため、g++を使用しないでください。したがって、これを使用すると、移植性のないコードが保証されます。 C++ 11に依存できる場合は(今までにできるでしょうか?)、nullptrを使用してください。そうでない場合、NULLが唯一の移植可能なオプションです。

53
ShadowRanger

NULLはCからC++に取って代わられ、C++ 11より前ではそのCの意味を採用しました。

c ++ 11まで:マクロNULLは、実装で定義されたNULLポインター定数です。これは、ゼロに評価される整数型の整数定数式右辺値です。

次に、C++ 11は、タイプstd::nullptr_tの専用のNULLポインターリテラルnullptrを導入しました。ただし、おそらく下位互換性のために、マクロNULLは削除されませんでした。コンパイラーが整数型またはポインター型として定義できるようになったため、その定義は少し緩和されました。

C++ 11以降:値がゼロの整数リテラル、またはstd :: nullptr_t型のprvalue

NULLを使用すると、オーバーロード解決で実装定義の動作が得られます。たとえば、NULL- macroの整数バージョンを使用するコンパイラを使用した次のコードを検討してください。次に、関数に渡されるパラメーターとしてNULLを使用する呼び出しは、あいまいさを引き起こす可能性があります。

struct SomeOverload {

    SomeOverload(int x) {
        cout << "taking int param: " << x << endl;
    }
    SomeOverload(void* x) {
        cout << "taking void* param: " << x << endl;
    }
};

int main() {

    int someVal = 10;

    SomeOverload a(0);
    SomeOverload b(&someVal);

    // SomeOverload c(NULL);  // Call to constructor is ambiuous
    SomeOverload d(nullptr);
}

そのため、ポインタ型を表現する場合は、nullptrを使用することをお勧めします。

また、__nullは使用しないでください。これはコンパイラ固有の移植性のない定数です。対照的に、nullptrは完全に移植可能です。

11
Stephan Lechner

NULLは、nullポインターの古いCシンボルです。 C++は伝統的に0をNULLポインターに使用し、C++ 11標準nullptr以来使用していました。

xがポインターではないように思えると、xをヌルポインターに初期化できず、__nullシンボルはおそらくヌル用のコンパイラー内部シンボルです。 (標準C++には実際には存在しない概念です)。

xをデフォルト状態に初期化する場合は、MyClassデフォルトコンストラクターに依存して、オブジェクトとそのメンバー変数を適切なデフォルト値に初期化する必要があります。