C++里的nullptr和NULL有什么区别?(强类型指针常量)

19次阅读

NULLptr 是类型安全的空指针字面量,类型为 std::nullptr_t,可隐式转换为任意指针类型,但不转换为整数类型,从而避免 NULL 在重载中的二义性问题。

C++里的nullptr和NULL有什么区别?(强类型指针常量)

nullptr 是类型安全的空指针字面量

nullptrc++11 引入的关键字,其类型是 std::nullptr_t,能隐式转换为任意指针类型,但**不会隐式转换为整数类型**。这直接解决了 NULL函数重载时的二义性问题。

常见错误现象:

void func(int) { std::cout << "intn"; }
void func(char*) { std::cout << "ptrn"; }
func(NULL); // 调用 func(int),不是预期的 ptr 版本
func(nullptr); // 正确调用 func(char*)

  • NULL 通常定义为 0((void*)0),在 C++ 中本质是整数或不兼容的 void* 类型
  • nullptr 的类型明确、唯一,编译器可据此做精确匹配
  • 所有现代标准(C++11 及以上)都应优先使用 nullptr

NULL 的定义依赖宏且行为不一致

NULL 不是语言关键字,而是头文件中定义的宏(如 #define NULL 0#define NULL ((void*)0)),具体展开取决于实现和包含的头文件( 等)。

  • 在 C++98/03 中,NULL 常被展开为 0,导致它和整数字面量完全等价
  • 某些旧编译器对 ((void*)0) 的处理可能违反 C++ 标准(void* 不能隐转为其他指针)
  • 混用 C 头文件(如 )时,NULL 行为更不可控

赋值和模板推导中 nullptr 更可靠

在需要显式类型信息的上下文中,nullptr 能让编译器准确推导指针意图;而 NULL 可能触发整数分支或推导失败。

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

使用场景示例:

auto p = nullptr;        // p 类型是 std::nullptr_t
auto q = NULL; // q 类型是 int(如果 NULL 定义为 0)

template void take_ptr(T*);
take_ptr(nullptr); // OK:T 被推导为任意类型
take_ptr(NULL); // 错误:无法从 int 推导出 T*

  • nullptr 初始化智能指针(std::unique_ptr p = nullptr;)是标准写法
  • constexpr 上下文中,nullptr 是字面量常量NULL 不一定满足要求
  • 静态断言中判断空指针也应基于 nullptr,比如 static_assert(std::is_same_v);

实际编码中应该彻底弃用 NULL

除了维护极老的 C++03 代码(且不打算升级标准),没有理由继续使用 NULL。它的“兼容性”代价远高于收益。

  • Clang 和 GCC 在 C++11+ 模式下会对 NULL 发出 -Wzero-as-null-pointer-constant 警告
  • 现代代码审查工具(如 clang-tidy)默认建议替换 NULL → nullptr
  • 即使跨平台,nullptr 在所有 C++11 兼容编译器中语义完全一致;NULL 则不然

真正容易被忽略的是:有些团队在头文件里自定义 #define NULL nullptr,看似省事,实则掩盖了历史代码中对 NULL 的整数误用——这种宏掩盖比直接删掉更危险。

text=ZqhQzanResources