C++怎么用空指针 C++中nullptr和NULL的区别【重点】

2次阅读

c++11起空指针必须用NULLptr:它是独立类型std::nullptr_t,专用于指针上下文,避免重载歧义、类型退化和模板推导错误,且无需头文件;null是宏,定义不稳定,易引发隐式转换问题。

C++怎么用空指针 C++中nullptr和NULL的区别【重点】

空指针在C++里必须用 nullptr,不是 NULL0

现代C++(C++11起)规定:空指针字面量唯一合法写法是 nullptr。它是个独立类型(std::nullptr_t),专用于指针上下文,不会被误认为整数。

常见错误现象:NULL 在有些头文件里定义为 0,在函数重载时可能调用错版本;int* p = 0; 虽能编译,但语义模糊,且无法区分“空指针”和“整数字面量0”。

  • nullptr 只能赋给指针类型(包括智能指针),编译器会严格检查
  • NULL 是宏,通常展开为 0((void*)0),在C++中后者不合法,前者导致类型退化
  • 函数重载场景下差异最明显:void f(int); void f(char*); f(NULL); 会调 f(int),而 f(nullptr) 正确匹配 f(char*)

nullptrNULL 的兼容性与头文件无关

nullptr 是语言关键字,不需要任何头文件;NULL 来自 <cstddef></cstddef> 或其他C头文件(如 <stdio.h></stdio.h>),但它的定义不稳定——标准只要求它是空指针常量,没规定具体形式。

使用场景:跨平台或混用C/C++代码时,NULL 可能因编译器/标准库实现不同而行为不一;nullptr 则始终一致。

立即学习C++免费学习笔记(深入)”;

  • 即使包含 <cstddef></cstddef>,也不该用 NULL 初始化指针
  • 模板推导中 nullptr 能正确推成 std::nullptr_tNULL 推成 intlong,容易出错
  • constexpr 上下文中,nullptr 是字面量常量,NULL 不一定(取决于其宏定义)

判断空指针别用 == NULL,统一用 == nullptr

虽然 p == NULL 通常能通过编译,但它掩盖了类型意图,且在自定义类重载 operator== 时可能意外触发非指针逻辑。

性能上无差异,但可读性和静态检查收益明确:编译器对 nullptr 的比较有更好诊断能力(比如检测是否对非指针类型做 == nullptr)。

  • 推荐写法:if (ptr == nullptr),而不是 if (!ptr)if (ptr == NULL)
  • !ptr 虽简洁,但依赖隐式转换,对某些智能指针(如自定义的)可能失效或不直观
  • 静态分析工具(如 clang-tidy)默认警告 == NULL,鼓励迁移到 == nullptr

老代码里遇到 NULL 怎么安全替换

直接全局替换风险高——有些地方 NULL 实际用作整数零(比如数组索引、errno赋值),不能一概而论。

实操建议分三步走:

  • 先用编译器警告定位真正用作空指针的地方:开启 -Wzero-as-null-pointer-constant(Clang/GCC)
  • 只替换出现在指针声明、初始化、比较、return语句右侧的 NULL
  • 特别注意宏定义内部、条件编译块、第三方头文件包含路径中的 NULL,这些不建议动

一个典型安全替换示例:char* buf = NULL;char* buf = nullptr;;但 memset(p, NULL, n); 里的 NULL 是整数0,应改为 0

最易被忽略的是函数参数传递:比如 foo(NULL),必须确认 foo 声明中该参数确实是指针类型,否则改了反而引入新bug

text=ZqhQzanResources