C++11で新たに導入されたnullptr
キーワードおよびstd::nullptr_t
型に関するメモ。
まとめ:
nullptr
キーワードはヌルポインタ定数を表すポインタリテラル。C++03以前の値0
, マクロNULL
とは別に新たに追加された。nullptr
の型はstd::nullptr_t
型と定義されるが、ユーザプログラム中でstd::nullptr_t
を直接利用することはまず無い。- おまけ:C/C++言語の両者においてマクロ
NULL
は処理系定義のヌルポインタ定数。
C++03以前からある特例ルール「値0はヌルポインタ定数としても扱う」に起因するオーバーロード問題を解消するために導入された。
void f(int); // [A] int型 void f(char*); // [B] char*型 // C++98/03 f(0); // 0はint型リテラルとみなされ[A]が呼ばれる f((char*)0); // 明示的な型キャストを行えば[B]が呼ばれる f((void*)0); // NG: [A]と[B]でオーバーロード解決ができない f(NULL); // NULLの展開結果は整数型定数とみなされ[A]が呼ばれる // C++11 f(0); // [A]が呼ばれる f(nullptr); // [B]が呼ばれる f(NULL); // 処理系依存
なお、C++11標準でもヌルポインタ定数としての0
およびNULL
の意味は変更されておらず、両者の利用は特に非推奨(deprecated)とされていない。
#include <cstddef> int* p1 = 0; // OK int* p2 = NULL; // OK int* p3 = nullptr; // OK(C++11のみ)
nullptrキーワードとnullptr_t型
nullptr
キーワードはポインタリテラル(pointer literal)を表しており、std::nullptr_t
型のprvalue(≒右辺値)と定義される。std::nullptr_t
型の値、つまりnullptr
はヌルポインタ定数(null pointer constant)とされ、任意のポインタ型へと変換可能。またbool
型の値false
へも変換可能(例:if文の条件式でも使える)。
なお、std::nullptr_t
型は標準ヘッダ <cstddef> にてtypedefされているが、ユーザプログラム中ではstd::nullptr_t
型を直接利用する機会は少ない*1。一部のライブラリコードではstd::nullptr_t
型を利用するケースがある(例:std::unique_ptr
, std::shared_ptr
, std::function
クラステンプレートなど)。
N3337 2.14.7/p1, 3.9.1/p10, 4.12/p1(一部), 18.2/p9より引用。
1 The pointer literal is the keyword
nullptr
. It is a prvalue of typestd::nullptr_t
. [Note:std::nullptr_t
is a distinct type that is neither a pointer type nor a pointer to member type; rather, a prvalue of this type is a null pointer constant and can be converted to a null pointer value or null member pointer value. See 4.10 and 4.11. -- end note]
10 A value of type
std::nullptr_t
is a null pointer constant (4.10). Such values participate in the pointer and the pointer to member conversions (4.10, 4.11).sizeof(std::nullptr_t)
shall be equal tosizeof(void*)
.
1 (snip) A prvalue of type
std::nullptr_t
can be converted to a prvalue of typebool
; the resulting value isfalse
.
9
nullptr_t
is defined as follows:namespace std { typedef decltype(nullptr) nullptr_t; }The type for which
nullptr_t
is a synonym has the characteristics described in 3.9.1 and 4.10.
2012-10-29追記:The View from Aristeia: The Standard works in Circular Ways で、C++11標準のnullptr
とnullptr_t
が循環定義されている点を言及。
nullptr vs. 0 vs. NULL
C++11標準におけるヌルポインタ定数 nullptr, 0, NULL の定義は下記通り。
- nullptr
- 予約済みキーワード。任意のポインタ型に対するヌルポインタ定数を表すポインタリテラル。
- 0
- 整数型(
int
)の定数値0
、または任意のポインタ型に対するヌルポインタ定数として扱うことができる整数リテラル。 - NULL
- 標準ヘッダ <cstddef> にてヌルポインタ定数として定義される処理系定義のマクロ。*2 *3
N3337 4.10/p1, 18.2/p3より引用(下線部は強調)。
1 A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type
std::nullptr_t
. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type. Such a conversion is called a null pointer conversion. Two null pointer values of the same type shall compare equal. The conversion of a null pointer constant to a pointer to cv-qualified type is a single conversion, and not the sequence of a pointer conversion followed by a qualification conversion (4.4). A null pointer constant of integral type can be converted to a prvalue of typestd::nullptr_t
. [Note: The resulting prvalue is not a null pointer value. -- end note]
3 The macro NULL is an implementation-defined C++ null pointer constant in this International Standard (4.10).194
脚注194) Possible definitions include0
and0L
, but not(void*)0
.
関連URL
*1:N2431でも "We do not expect to see much direct use of nullptr_t in real programs." と言及。
*2:C言語のマクロ NULL も、ヌルポインタ定数を表す処理系定義のマクロと定義されている。"The macros are NULL which expands to an implementation-defined null pointer constant;"(7.17/p3)
*3:大抵のC++処理系では #define NULL 0 となっている。一方、大抵のC処理系では #define NULL ((void*)0) とされており、ヌルポインタと NULL に関する混乱に拍車をかけている。また、gccでは独自拡張キーワードを用いて #define NULL __null としている。