- cpp11[meta cpp]
nullptr
は、ヌルポインタ値を表すキーワードである。
int* p = nullptr;
C++03まで、ヌルポインタを表すために0
数値リテラルやNULL
マクロを使用していた。C++11からは、nullptr
キーワードでヌルポインタ値を表すことを推奨する。
特定の型へのポインタではなく、nullptr
のみを受け取りたい場合は、std::nullptr_t
型を使用する。
nullptr
はスカラ型である。
nullptr_t
型は、任意の型へのポインタ、任意のメンバ型へのポインタに変換できる。sizeof(
nullptr_t
)
の値は、sizeof(void*)
と等値である。nullptr_t
型の右辺値はbool
型の右辺値に変換でき、その結果値はfalse
となる。nullptr_t
型の値は整数型にreinterpret_cast
でキャストできる。その結果は、(void*)0
を整数型に変換することと同じとなる。reinterpret_cast
のキャスト先の型にnullptr_t
を指定することはできない。
nullptr_t
型は、以下の関係演算が可能である:
bool operator==(nullptr_t, nullptr_t);
bool operator!=(nullptr_t, nullptr_t);
bool operator<(nullptr_t, nullptr_t);
bool operator<=(nullptr_t, nullptr_t);
bool operator>(nullptr_t, nullptr_t);
bool operator>=(nullptr_t, nullptr_t);
2つのnullptr_t
型を比較した場合、==
、<=
、>=
演算子の結果はtrue
となり、それ以外の演算子はfalse
となる。
#include <iostream>
int main()
{
int* p = nullptr;
if (!p) {
std::cout << "p is nullptr" << std::endl;
}
}
p is nullptr
以下のような関数テンプレートを考える:
template <class T>
void f(T p);
この関数にヌルポインタ値を渡したい場合、0
やNULL
マクロを使用すると、テンプレートの型推論によって整数型と見なされてしまっていた。これによって、引数をほかの関数に転送するプログラムを書く際に型が合わない問題が発生した。
この問題を回避するために、以下のようなヌルポインタ値を取得する関数がユーザーによって書かれていた:
template <class T>
T* nullptr_value()
{
return 0;
}
int* p = nullptr_value<int>();
これはユーザーの工夫によって問題を解決しているが、このような状況をより簡単に解決し、C++を教え、学ぶのをより容易にするために、nullptr
キーワードが導入された。
nullptr
はキーワードとして定義されることが決まる前に、いくつかの設計選択があった。
以下のような、任意のポインタ型に変換可能なクラスとして定義することが提案された:
const
class {
public:
// 任意のポインタ型への変換演算子
template <class T>
operator T*() const
{ return 0; }
// 任意のメンバポインタ型への変換演算子
template <class C, class T>
operator T C::*() const
{ return 0; }
private:
void operator&() const; // アドレスは取得できない
} nullptr = {};
これは言語機能ではなくライブラリで解決する案である。この案の問題としては、nullptr
オブジェクトを使用する前に、ヘッダをインクルードしなければならない、というものがある。ヌルポインタ値は多くの一般的な状況で必要になるため、ヘッダをインクルードしない選択肢として、キーワードのnullptr
が採用された。