应使用 nullptr 而非 NULL 或 0:因 NULL 和 0 是整型,重载时易误匹配 int 版本;nullptr 类型为 std::nullptr_t,只匹配指针重载,且具备类型安全、编译期检查、语义清晰等优势。

函数重载时调用哪个版本?这是最常踩的坑
当你写 func(NULL),编译器大概率会选 func(int) 而不是 func(char*)——哪怕你本意是传空指针。因为 NULL 本质就是整数 0,而 0 是更匹配 int 的精确类型。
换成 func(nullptr) 就没歧义了:它只能转成指针,所以直接绑定到 func(char*)。
-
NULL在重载中可能“悄悄”走错分支,bug 难复现、难调试 -
nullptr让重载解析结果可预测,且编译期报错(比如没有匹配的指针重载),比运行时逻辑错更早暴露问题 - 尤其注意带
std::string、const char*、int混合重载的 API,NULL极易误入字符串构造或整型分支
模板推导出什么类型?auto 和容器键值很敏感
写 auto p = NULL;,推导结果是 int;而 auto q = nullptr; 推导出的是 std::nullptr_t——这直接影响后续赋值、比较甚至 SFINAE 判定。
例如:std::map,你想查空指针:m.find(nullptr) 合法;但 m.find(0) 或 m.find(NULL) 会编译失败,因为 0 和 NULL 是 int,和 int* 类型不匹配。
立即学习“C++免费学习笔记(深入)”;
- 所有泛型代码(模板参数、
auto、decltype、容器查找)必须用nullptr - 别依赖
!p做空指针判断——万一p是自定义类型且重载了operator!,行为就失控了 - 显式写
p == nullptr,语义清晰,且能被静态分析工具准确识别
新项目还能用 NULL 吗?工程规范怎么落地
不能。C++11 已是 15 年前的标准,所有主流编译器(GCC 4.7+、Clang 3.3+、MSVC 2015+)都完整支持 nullptr。继续用 NULL 不是兼容性需要,而是习惯或疏忽。
- 旧代码迁移时,全局搜索替换
= NULL→= nullptr,但注意排除 C 头文件引用(如#include中的NULL宏定义) - 禁用
-Wzero-as-null-pointer-constant(GCC/Clang)这类警告,它会把NULL当作过时用法提醒 - CI 流程中加入 clang-tidy 规则
modernize-use-nullptr,自动检测并修复 - 嵌入式等极少数 C++03 环境,不要退化回
NULL,改用封装:#define MY_NULLPTR (static_cast<:nullptr_t>(0))(需确认编译器支持std::nullptr_t)
为什么 0 和 NULL 都不行,偏偏要 nullptr?
因为 C++ 的空指针语义长期被“数字 0”污染:0 是整数、是字面量、还能参与算术——而空指针不该加减、不该比较大小、不该隐式当布尔用。它唯一合法身份就是“指向无”的标记。
nullptr 把这个意图固化进语言:它不可算术(nullptr + 1 直接编译失败)、不可转整(int x = nullptr; 报错)、只服务于指针上下文。这不是语法糖,是类型系统的补丁。
- 最容易忽略的点:在跨语言绑定(如 Python/C++ 扩展)或 ABI 敏感场景中,
nullptr的二进制表示与平台 NULL 一致,但它的类型约束能防止头文件误包含导致的隐式转换 - 别在宏里拼接
nullptr(如#define SAFE_DELETE(p) do { delete p; p = nullptr; } while(0)是 OK 的;但#define NULLISH nullptr不推荐,破坏关键字语义)










