从本质上

  • 0 是 int 型的字面值常量

  • NULL 是预处理变量,定义在 cstdlib 中,其值是0

  • nullptr 是 nullptr_t 类型的字面值。

在C的头文件中,通常定义如下:#define NULL ((void*)0),但是在C++中,它是这样定义的:#define NULL 0 。

void* 的强转

C++ 之父尽量避免使用宏,在 C++ 标准中,我们可以见到一个词语叫做 null pointer constant,其实在C++11标准前,是只承认 0 为 null pointer constant的。即没有类型的指针,包容所有指针的指针。

所以,在C++中,我们也经常能听到一个说法,就是赋予null pointer,应该是使用0,而非NULL。而nullptr pointer constant这个词语在C++11发布后,终于再添了一个成员,就是nullptr。

nullptr的出现背景,其实是很简单的,C++哲学上来说就是C++之父一直对null pointer没有一个正式的表示感到非常不满,而更工程的来说,就是关于重载这个问题。

0

0 这个东西在 C++ 中,在 C11 之前被认为是空指针常量,但是会带来重载问题。为什么不用 (void*)0 是因为 Bjarne 本人的哲学观点,认为 0 表示 “not there” 这个含义。

纯虚函数为什么是用=0来设置的?函数实现”not there”。

nullptr

由于 NULL 和 0 在 C++ 中本质没有了区别,所以重载时就会出现问题。所以就出现了 nullptr ,nullptr 是 nullptr_t 类型的常量,而该类型定义了转到任意指针类型的转换操作符,同时不允许该类型的对象转换到非指针类型。

  1. void foo(int); //(1)
  2. void foo(void*); //(2)
  3. foo(NULL); // 重载决议选择 (1),但调用者希望是 (2)

有趣的是 std::nullptr_t 的定义

  1. typedef decltype(nullptr) nullptr_t; // 通过字面量反过来定义类型

nullptr 只是一个区分 0 和 NULL 区别的东西