用 == nullptr 判断最安全,因其明确、类型安全、无宏依赖且可优化;null 和 ptr == 0 易引发重载歧义或语义模糊;智能指针优先用 !ptr;野指针无法通过空检防范。

用 == nullptr 判断最安全
在现代 C++(C++11 及以后),nullptr 是专门用于表示空指针的字面量,类型为 std::nullptr_t,能避免 NULL 或 0 带来的函数重载歧义。直接写 ptr == nullptr 是最清晰、最不易出错的方式。
常见错误包括:
- 写成
if (ptr)—— 虽然语法合法且等价,但可读性差,尤其对新手或代码审查者不友好 - 写成
if (ptr == NULL)——NULL在多数实现中是0或0L,可能被误推导为整型,导致模板或重载函数调用异常 - 写成
if (!ptr)—— 同样合法,但语义不如== nullptr明确,且容易和布尔逻辑混淆
不要解引用前忘记判断
空指针解引用(*ptr 或 ptr->member)是未定义行为,程序可能崩溃、静默出错或看似正常运行——这恰恰最危险。
典型场景:
- 函数参数传入指针,未约定非空,调用方可能传
nullptr - 容器查找(如
std::map::find)返回end()迭代器,若错误地当成指针使用(比如取&*it后没检查it != end()) - 动态分配失败时
new抛异常,但用了new(std::nothrow)会返回nullptr,必须显式判断
示例:
int* p = new(std::nothrow) int[100];
if (p == nullptr) {
// 处理分配失败
return;
}
// 此时才能安全使用 p
智能指针不用手动判空,但仍有陷阱
std::unique_ptr 和 std::shared_ptr 支持隐式转换为 bool,所以 if (ptr) 是惯用写法,本质调用的是 operator bool(),内部就是判断是否持有非空原始指针。
但要注意:
-
std::weak_ptr不支持隐式转bool,必须先调用lock()得到shared_ptr,再判断;否则直接用expired() - 自定义删除器(deleter)不会影响空状态判断逻辑,但若删除器本身有副作用,空指针仍会触发调用(除非你显式检查后再 reset)
- 从裸指针构造智能指针时,若传入
nullptr,该智能指针就是空的,if (ptr)为false—— 这没问题,但别误以为“构造成功就一定非空”
结构体成员指针或函数指针不能用 == nullptr 直接比
指向成员的指针(如 int A::*p)和函数指针(如 void (*fp)())虽也可能是空值,但标准规定它们**不能与 nullptr 比较**。比较结果未定义,编译器可能报错或静默通过但行为不可靠。
正确做法:
- 成员指针:用
== 0或直接if (!p)(C++11 起允许) - 函数指针:同理,
if (fp == nullptr)在部分编译器(如 GCC/Clang)允许,但严格来说应写if (fp)或if (fp != nullptr)并确认编译器支持;更稳妥是if (fp) - 统一建议:对这类特殊指针,优先查文档或用
static_assert验证其可空性,避免跨平台隐患
空指针判断本身很简单,难的是养成「每次解引用前都确认」的习惯,以及区分不同指针类型的语义边界——尤其是成员指针和函数指针,它们的“空”不是地址意义上的零,而是语言层面的特殊值。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











