nullptr 是类型安全的空指针字面量,类型为 std::nullptr_t,可隐式转换为任意指针类型,但不转换为整数类型,从而避免 NULL 在重载中的二义性问题。

nullptr 是类型安全的空指针字面量
nullptr 是 C++11 引入的关键字,其类型是 std::nullptr_t,能隐式转换为任意指针类型,但**不会隐式转换为整数类型**。这直接解决了 NULL 在函数重载时的二义性问题。
常见错误现象:
void func(int) { std::cout << "int\n"; }<br>void func(char*) { std::cout << "ptr\n"; }<br>func(NULL); // 调用 func(int),不是预期的 ptr 版本<br>func(nullptr); // 正确调用 func(char*)
-
NULL通常定义为0或((void*)0),在 C++ 中本质是整数或不兼容的 void* 类型 -
nullptr的类型明确、唯一,编译器可据此做精确匹配 - 所有现代标准(C++11 及以上)都应优先使用
nullptr
NULL 的定义依赖宏且行为不一致
NULL 不是语言关键字,而是头文件中定义的宏(如 #define NULL 0 或 #define NULL ((void*)0)),具体展开取决于实现和包含的头文件(<cstddef>、<cstdio> 等)。
- 在 C++98/03 中,
NULL常被展开为0,导致它和整数字面量完全等价 - 某些旧编译器对
((void*)0)的处理可能违反 C++ 标准(void* 不能隐转为其他指针) - 混用 C 头文件(如
<stdio.h>)时,NULL行为更不可控
赋值和模板推导中 nullptr 更可靠
在需要显式类型信息的上下文中,nullptr 能让编译器准确推导指针意图;而 NULL 可能触发整数分支或推导失败。
立即学习“C++免费学习笔记(深入)”;
使用场景示例:
auto p = nullptr; // p 类型是 std::nullptr_t<br>auto q = NULL; // q 类型是 int(如果 NULL 定义为 0)<br><br>template<typename T> void take_ptr(T*);<br>take_ptr(nullptr); // OK:T 被推导为任意类型<br>take_ptr(NULL); // 错误:无法从 int 推导出 T*
- 用
nullptr初始化智能指针(std::unique_ptr<T> p = nullptr;)是标准写法 - 在
constexpr上下文中,nullptr是字面量常量,NULL不一定满足要求 - 静态断言中判断空指针也应基于
nullptr,比如static_assert(std::is_same_v<decltype std::nullptr_t>);</decltype>
实际编码中应该彻底弃用 NULL
除了维护极老的 C++03 代码(且不打算升级标准),没有理由继续使用 NULL。它的“兼容性”代价远高于收益。
- Clang 和 GCC 在 C++11+ 模式下会对
NULL发出-Wzero-as-null-pointer-constant警告 - 现代代码审查工具(如 clang-tidy)默认建议替换
NULL → nullptr - 即使跨平台,
nullptr在所有 C++11 兼容编译器中语义完全一致;NULL则不然
真正容易被忽略的是:有些团队在头文件里自定义 #define NULL nullptr,看似省事,实则掩盖了历史代码中对 NULL 的整数误用——这种宏掩盖比直接删掉更危险。










