C++ nullptr是什么类型 C++ std::nullptr_t类型解析【新特性】

nullptr 是 C++11 引入的空指针字面量,类型为 std::nullptr_t;它仅可隐式转换为任意指针类型,不支持算术运算或转为整数,且在函数重载中能精准匹配指针参数,避免 NULL 或 0 引发的二义性。

nullptr 不是类型,它是一个字面量(literal),其类型是 std::nullptr_t。这是 C++11 引入的关键改进,用来替代容易引发二义性的 NULL(本质是 0void*)和整数字面量 0

为什么不能把 nullptr 当作 void* 或整数用

常见错误是试图对 nullptr 做算术运算或隐式转成整数:

int x = nullptr;          // 错误:no viable conversion
int y = nullptr + 1;      // 错误:invalid operands to binary expression
void* p = nullptr + 4;    // 错误:cannot add to

'std::nullptr_t'

std::nullptr_t 是一个空类类型(empty class type),只定义了到所有指针类型的隐式转换,不支持任何其他运算。它的设计目标非常明确:只用于表示空指针值,不参与计算。

std::nullptr_t 在函数重载中的关键作用

当多个重载函数分别接受 intconst char* 和指针时,nullptr 能精准匹配指针版本,而 0NULL 可能触发非预期的整数重载:

void foo(int)     { std::cout << "int\n"; }
void foo(char*)   { std::cout << "char*\n"; }
void foo(void*)   { std::cout << "void*\n"; }

foo(0); // 调用 foo(int),不是你想要的 foo(nullptr); // 明确调用 foo(void*)

这种行为差异在模板推导中更明显:template void bar(T) 接收 nullptr 时,T 被推导为 std::nullptr_t,而非 intvoid*

std::nullptr_t 的底层定义与兼容性细节

标准规定 std::nullptr_t 是一个独立的、不可实例化的类型,通常实现为:

namespace std {
  typedef decltype(nullptr) nullptr_t;
}

实际使用中需注意:

  • sizeof(std::nullptr_t) 通常是 1(空类),但标准未强制要求
  • 不能定义 std::nullptr_t 的变量并赋值(如 std::nullptr_t n = nullptr; 合法,但 n = nullptr 之后不能再赋其他值——因为没定义赋值操作符)
  • 不能继承 std::nullptr_t,它是 final-like(无用户定义构造/析构/赋值)
  • C++11 起支持,旧代码若需兼容 C++98,仍需避免直接依赖该类型

真正容易被忽略的是:即使你从不显式写 std::nullptr_t,只要用了 nullptr,编译器就在背后依赖这个类型做类型安全检查——它不像宏替换那样透明,而是深度融入类型系统。一旦涉及模板元编程或 SFINAE,std::nullptr_t 的存在就立刻变得不可绕过。