NULL本质是整数0,重载时优先匹配int参数而非指针;nullptr是std::nullptr_t类型,只向指针隐式转换,确保类型安全。

函数重载时传 NULL 为什么常调错版本?
因为 NULL 本质是宏,C++ 中多数编译器定义为 0(int 类型),不是指针。当存在两个重载函数时,编译器优先匹配整数参数——哪怕你本意是传空指针。
-
void func(int)和void func(char*)同时存在时:func(NULL)会调用func(int),而不是你预期的指针版本 -
func(nullptr)则**一定**匹配func(char*),因为nullptr的类型是std::nullptr_t,只向指针类型隐式转换 - VS、GCC、Clang 在 C++11+ 模式下行为一致,但老项目若混用 C 风格头文件(如
),NULL定义可能更混乱
模板推导中 NULL 会悄悄“变类型”?
是的。NULL 是整数,进模板后常被推成 int;而 nullptr 进模板永远是 std::nullptr_t,再由上下文决定转成什么指针——这才是你想要的语义。
-
auto x = NULL;→x类型是int(危险!后续误当指针用就崩) -
auto y = nullptr;→y类型是std::nullptr_t,且能安全用于int*、std::string*等任何指针上下文 - 智能指针初始化也一样:
std::unique_ptr编译通过但语义错误;p = NULL; std::unique_ptr才是标准写法p = nullptr;
能不能把 NULL 全局替换成 nullptr?要注意什么?
可以,但别用 IDE “全文件替换”一刀切——尤其注意 C 头文件和跨语言接口代码。
- 纯 C++11+ 项目:直接全局搜索
= NULL、(NULL)、== NULL,替换成= nullptr等,基本安全 - 含 C 代码或
extern "C"接口时,NULL可能被 C 编译器要求(比如系统 API 参数),此时保留NULL更稳妥 - 宏定义里用到
NULL(如#define SAFE_DELETE(p) do { delete p; p = NULL; } while(0)),建议改写为p = nullptr,但需确认所有使用该宏的指针类型兼容 - 检查构建日志:替换后若出现
error: cannot convert 'int' to 'xxx*' in assignment,说明某处NULL原本被当整数用了(比如数组索引),不能硬换
不升级到 C++11 就不能用 nullptr?
是的。nullptr 是 C++11 标准关键字,C++98/03 编译器(如旧版 VC6、GCC 4.1 以下)根本不认识它,会报 error: 'nullptr' was not declared in this scope。
立即学习“C++免费学习笔记(深入)”;
- 若必须支持老标准,可用轻量模拟(非完全等价):
const class nullptr_t { public: templateoperator T*() const { return 0; } template operator T C::*() const { return 0; } private: void operator&() const; } nullptr = {}; - 但强烈不建议在生产环境手写模拟——它无法参与 SFINAE、不支持
decltype(nullptr)、与标准库智能指针交互可能出问题 - 真正要长期维护的老项目,优先考虑升级工具链;临时兼容可加条件编译:
#if __cplusplus >= 201103L分支处理
nullptr 不是“可选项”,而是类型安全的底线——它不解决新功能,但堵住了 NULL 留下的所有歧义入口。最易忽略的点是:**连 if (ptr == NULL) 这种看似无害的判断,都可能因宏展开或重载干扰,在复杂模板中引发静默类型退化**。











