618

現在、多くの新機能を備えた C++11 があります。(少なくとも私にとっては) 面白くて紛らわしいのは newnullptrです。

まあ、厄介なマクロはもう必要ありませんNULL

int* x = nullptr;
myclass* obj = nullptr;

それでも、私はどのようにnullptr機能するのかわかりません。たとえば、ウィキペディアの記事には次のように書かれています。

C++11 では、null ポインター定数として機能する新しいキーワードnullptr を導入することで、これを修正しています。これはnullptr_t 型であり、暗黙的に変換可能であり、任意のポインター型またはメンバーへのポインター型と比較できます。bool を除いて、暗黙的に変換したり、整数型と比較したりすることはできません。

それはどのようにキーワードであり、型のインスタンスですか?

nullptrまた、古き良きよりも優れている別の例(ウィキペディアのもの以外)はあり0ますか?

4

14 に答える 14

429

それはどのようにキーワードであり、型のインスタンスですか?

これは驚くべきことではありません。trueとは両方ともfalseキーワードであり、リテラルとして型 ( bool) を持ちます。nullptrは型のポインタ リテラルstd::nullptr_tであり、prvalue です ( を使用してそのアドレスを取得することはできません&)。

  • 4.10about pointer conversion は、 型の prvalue がstd::nullptr_tヌル ポインター定数であり、整数型のヌル ポインター定数を に変換できることを示していstd::nullptr_tます。反対方向は使用できません。これにより、ポインターと整数の両方の関数をオーバーロードしnullptr、ポインターのバージョンを選択するために渡すことができます。渡すNULL0、混乱してintバージョンを選択します。

  • の整数型へのキャストにはnullptr_t, が必要であり、整数型へのreinterpret_castのキャストと同じセマンティクスを持ちます(void*)0(マッピングの実装が定義されています)。Aは、どのポインター型にもreinterpret_cast変換できません。nullptr_t可能であれば暗黙の変換に依存するか、または を使用してstatic_castください。

  • 規格では、 である必要がsizeof(nullptr_t)ありますsizeof(void*)

于 2009-08-15T17:06:52.770 に答える
65

nullptrから: タイプ セーフで明確な Null ポインター:

新しい C++09 の nullptr キーワードは、普遍的な null ポインター リテラルとして機能する右辺値定数を指定し、バグが多く型付けが弱いリテラル 0 と悪名高い NULL マクロを置き換えます。したがって、nullptr は、30 年以上にわたる当惑、あいまいさ、およびバグに終止符を打ちます。次のセクションでは、nullptr 機能を紹介し、NULL および 0 の問題を修正する方法を示します。

その他の参照:

于 2009-08-15T17:02:18.363 に答える
37

複数の型へのポインターを受け取ることができる関数がある場合、それを呼び出すのNULLはあいまいです。これが現在回避されている方法は、int を受け入れ、それがNULL.

template <class T>
class ptr {
    T* p_;
    public:
        ptr(T* p) : p_(p) {}

        template <class U>
        ptr(U* u) : p_(dynamic_cast<T*>(u)) { }

        // Without this ptr<T> p(NULL) would be ambiguous
        ptr(int null) : p_(NULL)  { assert(null == NULL); }
};

では、実行時ではなくコンパイル時エラーになるようC++11にオーバーロードすることができます。nullptr_tptr<T> p(42);assert

ptr(std::nullptr_t) : p_(nullptr)  {  }
于 2009-08-16T06:46:58.347 に答える
10

nullptrなどの整数型に割り当てることはできませんがint、ポインター型にのみ割り当てることができます。などの組み込みポインタ型int *ptrまたは次のようなスマートポインタのいずれかstd::shared_ptr<T>

これは重要な違いだと思います。なぜなら、展開されたマクロはNULL整数型とポインタの両方に割り当てることができ、マクロはポインタの初期値としても機能するからです。NULL0int

于 2013-01-29T13:12:14.827 に答える
6

nullptrまた、古き良き0よりも優れている別の例(ウィキペディアのもの以外)はありますか?

はい。これは、製品コードで発生した (簡略化された) 実際の例でもあります。レジスタ幅が異なるプラットフォームにクロスコンパイルするときに gcc が警告を発行できたため、際立っていました (x86_64 から x86 にクロスコンパイルするときだけ、警告する理由はまだ正確にはわかりませんwarning: converting to non-pointer type 'int' from NULL)。

次のコードを検討してください (C++03):

#include <iostream>

struct B {};

struct A
{
    operator B*() {return 0;}
    operator bool() {return true;}
};

int main()
{
    A a;
    B* pb = 0;
    typedef void* null_ptr_t;
    null_ptr_t null = 0;

    std::cout << "(a == pb): " << (a == pb) << std::endl;
    std::cout << "(a == 0): " << (a == 0) << std::endl; // no warning
    std::cout << "(a == NULL): " << (a == NULL) << std::endl; // warns sometimes
    std::cout << "(a == null): " << (a == null) << std::endl;
}

次の出力が得られます。

(a == pb): 1
(a == 0): 0
(a == NULL): 0
(a == null): 1
于 2013-09-25T20:31:24.023 に答える
6

他の言語には、型のインスタンスである予約語があります。たとえば、Python:

>>> None = 5
  File "<stdin>", line 1
SyntaxError: assignment to None
>>> type(None)
<type 'NoneType'>

これは、None通常、初期化されていないものに使用されるため、実際にはかなり近い比較ですが、同時に などの比較None == 0は false です。

一方、プレーンCでは、 常に無効なアドレス(AFAIK)である0を返すマクロであるNULL == 0ため、真のIIRCを返します。NULL

于 2009-08-15T16:52:28.400 に答える
3

これは、標準でそのように指定されているため、キーワードです。;-) 最新のパブリック ドラフト (n2914) によると

2.14.7 ポインタリテラル [lex.nullptr]

pointer-literal:
nullptr

ポインタ リテラルはキーワードnullptrです。タイプの右辺値ですstd::nullptr_t

暗黙的に整数値に変換されないため便利です。

于 2009-08-15T17:00:47.243 に答える
-2

NULL は 0 である必要はありません。常に NULL を使用し、決して 0 を使用しない限り、NULL は任意の値にすることができます。0 の割り込みベクトルを持つ von Neuman マイクロコントローラをフラット メモリでプログラムすると仮定します。NULL が 0 で、NULL ポインタに何かが書き込まれると、マイクロコントローラはクラッシュします。NULL が 1024 で、1024 に予約変数がある場合、書き込みによってクラッシュすることはなく、プログラム内から NULL ポインターの割り当てを検出できます。これは PC では意味がありませんが、宇宙探査機、軍事または医療機器の場合、クラッシュしないことが重要です。

于 2015-07-31T20:31:51.737 に答える