最終更新日時:
が更新

履歴 編集

nullptr(C++11)

概要

nullptrは、ヌルポインタ値を表すキーワードである。

int* p = nullptr;

C++03まで、ヌルポインタを表すために0数値リテラルやNULLマクロを使用していた。C++11からは、nullptrキーワードでヌルポインタ値を表すことを推奨する。

特定の型へのポインタではなく、nullptrのみを受け取りたい場合は、std::nullptr_t型を使用する。

仕様

  • nullptrキーワードは、nullptr_t型の右辺値オブジェクトである。
  • nullptr_t型の値は、ヌルポインタを表す定数である。

型の分類

型変換

  • 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);

この関数にヌルポインタ値を渡したい場合、0NULLマクロを使用すると、テンプレートの型推論によって整数型と見なされてしまっていた。これによって、引数をほかの関数に転送するプログラムを書く際に型が合わない問題が発生した。

この問題を回避するために、以下のようなヌルポインタ値を取得する関数がユーザーによって書かれていた:

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が採用された。

関連項目

参照