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

nullptr 不是类型,它是一个字面量(literal),其类型是 std::nullptr_t。这是 C++11 引入的关键改进,用来替代容易引发二义性的 NULL(本质是 0 或 void*)和整数字面量 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 在函数重载中的关键作用
当多个重载函数分别接受 int、const char* 和指针时,nullptr 能精准匹配指针版本,而 0 或 NULL 可能触发非预期的整数重载:
立即学习“C++免费学习笔记(深入)”;
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 接收 nullptr 时,T 被推导为 std::nullptr_t,而非 int 或 void*。
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 的存在就立刻变得不可绕过。










