nullptr 是类型安全的空指针字面量,只能隐式转换为指针类型而不会转为整数;NULL 是宏(常为0),在重载函数中易引发歧义匹配。

nullptr 是类型安全的空指针字面量
nullptr 在 C++11 中被引入,本质是 std::nullptr_t 类型的纯右值,只能隐式转换为任意指针类型(包括成员指针),但**不会转换为整数类型**。而 NULL 通常是宏定义,比如 #define NULL 0 或 #define NULL ((void*)0) —— 前者是 int,后者在 C++ 中不合法(C++ 禁止 void* 隐式转其他指针),所以实际编译器常退化为 0 或 0L。
重载函数调用时避免歧义
当存在多个重载函数,参数分别是 int 和 char*(或任意指针)时,传 NULL 可能意外匹配 int 版本:
void foo(int) { std::cout << "int\n"; }
void foo(char*) { std::cout << "char*\n"; }
foo(NULL); // 输出 "int"(取决于 NULL 定义,但常见行为)
foo(nullptr); // 编译错误?不,它只匹配 char → 输出 "char"(唯一可行转换)
这是因为 nullptr 不能转成 int,而 NULL(若为 0)是 int,优先匹配 int 重载。
模板推导和 auto 推导更可靠
用 NULL 初始化模板参数或 auto 变量,类型可能不是你想要的:
立即学习“C++免费学习笔记(深入)”;
-
auto p = NULL;→p类型是int(不是指针!) -
auto p = nullptr;→p类型是std::nullptr_t,后续赋值给任何指针都合法 - 模板函数如
template→void bar(T*); bar(NULL); T推导失败(NULL不是指针类型),而bar(nullptr)可正确推导出T
与 sizeof、函数指针等场景的兼容性
nullptr 的大小始终与指针一致(sizeof(nullptr) == sizeof(void*)),且可直接赋值给函数指针:
void func() {}
void (*fp)() = nullptr; // 合法
// void (*fp)() = NULL; // 若 NULL 是 0,则 error:cannot convert 'int' to 'void (*)()' 某些平台对 NULL 宏的实现不统一,尤其跨编译器或混用 C/C++ 头文件时,nullptr 彻底规避了宏展开和整数/指针二义性问题。
真正容易被忽略的是:即使项目已全面使用 nullptr,第三方 C 头文件里仍可能带 NULL 宏;若你在 C++ 中写 if (p == NULL),虽能编译,但已失去类型安全优势——这种写法应一律改为 p == nullptr 或更推荐的 !p。










