nullptr 是类型安全的空指针字面量;C++11 前常用 0 或 NULL 表示空指针,但其整数本质易导致函数重载误判,如 void foo(int) 和 void foo(char*) 同时存在时调用 foo(0) 会匹配 int 版本而非指针版本。

nullptr 是类型安全的空指针字面量,0 不是
在 C++11 之前,0(或宏 NULL)常被用作空指针,但它本质是整数,编译器可能误判重载函数调用。比如:
void foo(int x) { cout << "int\n"; }
void foo(char* p) { cout << "ptr\n"; }
foo(0); // 调用 foo(int),不是 foo(char*)!而 foo(nullptr) 明确匹配指针重载。这是最根本的区别:nullptr 的类型是 std::nullptr_t,可隐式转换为任意指针类型,但不会转成整数类型。
初始化指针时必须用 nullptr,而非 0 或 NULL
现代 C++(C++11 起)中,所有裸指针、智能指针、容器迭代器的空值初始化都应统一用 nullptr:
-
int* p = nullptr;✅ 清晰、类型安全、可读性强 -
int* p = 0;❌ 语义模糊,可能触发整数重载歧义 -
int* p = NULL;❌NULL通常定义为0或0L,仍是整数,且依赖头文件(如cstddef) -
std::unique_ptr✅ 合法,ptr = nullptr; std::unique_ptr支持nullptr_t构造 -
std::unique_ptr❌ 编译失败(C++11 起禁止隐式整数→指针转换)ptr = 0;
模板和 auto 推导中 nullptr 更可靠
当指针参与模板参数推导或 auto 声明时,0 会推导为 int,导致意外行为:
auto p1 = nullptr; // p1 类型是 std::nullptr_t
auto p2 = 0; // p2 类型是 int
template
void bar(T* ptr) { /* ... */ }
bar(nullptr); // OK,T 被推为任意类型
bar(0); // 编译错误:无法从 int 推导 T*尤其在泛型容器、工厂函数或 SFINAE 场景下,用
0 容易触发硬错误或静默降级。立即学习“C++免费学习笔记(深入)”;
兼容性与遗留代码处理建议
如果项目需兼容 C++98/03,不能用
nullptr,则统一用0(不用NULL,避免宏污染),并加注释说明意图;但新代码一律禁用0初始化指针。Clang/GCC 可开启-Wzero-as-null-pointer-constant警告来捕获0作空指针的用法。VS 中对应警告是C4826。真正容易被忽略的是:即使在 C++11+ 项目里,
0仍可能出现在宏定义、第三方头文件、或旧风格 typedef(如typedef int* HANDLE;)中——此时它已不是空指针,而是整数字面量,直接赋给指针变量会触发编译器警告甚至错误。别信直觉,看类型。











