最安全的空指针判断方式是 if (ptr == nullptr)。它语义清晰、类型安全,避免与0或NULL的隐式转换歧义,且在重载解析中精准匹配指针类型,而0可能误调int重载。

用 == nullptr 判断最安全
在现代 C++(C++11 及以后),直接比较指针和 nullptr 是唯一推荐的方式。它语义清晰、类型安全,且能避免与整数 0 或宏 NULL 的隐式转换歧义。
常见错误包括写成 if (ptr == 0) 或 if (!ptr) —— 虽然多数情况下能工作,但 !ptr 依赖于指针到布尔的隐式转换,而 == 0 可能被误读为整数比较;更糟的是,如果有人把 NULL 定义为 0L 或其他类型,在模板或重载场景下可能引发意外匹配。
-
if (ptr == nullptr)明确表达“空指针”意图,编译器可做更好检查 - 不要用
if (ptr == NULL):C++11 后NULL通常只是0的别名,不具类型安全性 - 避免
if (!ptr)在接口契约严格的代码中(比如 static analysis 工具可能报弱判断)
nullptr 和 0 在函数重载时行为不同
这是最容易踩坑的点:当多个重载函数分别接受 int 和 int* 参数时,传 0 会绑定到 int 版本,而 nullptr 只能匹配指针类型。
void foo(int*) { std::cout << "ptr\n"; }
void foo(int) { std::cout << "int\n"; }
<p>foo(nullptr); // 输出 "ptr"
foo(0); // 输出 "int" —— 往往不是你想要的所以哪怕只是判断,也建议统一用 nullptr,保持语义一致性,避免后续扩展时因类型推导出错。
立即学习“C++免费学习笔记(深入)”;
判断前先确认指针变量已初始化
空指针判断本身没意义,如果指针是未初始化的野指针(比如栈上局部指针未赋值),它的值是随机的,== nullptr 几乎一定为假,但解引用会崩溃——这时问题不在判断逻辑,而在生命周期管理。
- 局部指针声明后立即初始化:
int* p = nullptr; - 类成员指针在构造函数初始化列表中设为
nullptr - 用智能指针(如
std::unique_ptr)替代裸指针,其默认构造即为空,且if (ptr)等价于if (ptr != nullptr),更安全
容器里的指针元素不能只靠 empty() 判断是否为空
像 std::vector<int></int> 或 std::list<void></void>,调用 empty() 检查的是容器是否含元素,不是里面每个指针是否为空。必须遍历并逐个比较:
std::vector<int*> vec = {new int(42), nullptr, new int(99)};
for (int* p : vec) {
if (p == nullptr) {
// 处理空指针情况
}
}漏掉这层检查,很容易在后续 *p 解引用时触发未定义行为。尤其在从 C API 接收指针数组时,文档常写“可能返回 NULL”,这种地方必须手动判空。
真正麻烦的从来不是怎么写那行 == nullptr,而是谁负责初始化、谁保证不提前释放、以及多线程环境下是否需要原子读取——这些比判断本身重得多。


















