文章

条款8:优先考虑nullptr而非0和NULL

nullptr 更安全,避免重载解析歧义,推荐取代 0/NULL。

条款8:优先考虑nullptr而非0和NULL

条款 8:优先考虑 nullptr 而非 0 和 NULL

原因一:0 和 NULL 本质是整型,不是指针

表达式实际类型
0int
NULL实现相关,通常是 intlong,但不是指针类型
nullptrstd::nullptr_t,可以隐式转换为任意类型的指针

原因二:函数重载中容易选错

1
2
3
4
5
6
7
void f(int);
void f(bool);
void f(void*);

f(0);        // 调用 f(int),不是你想的 f(void*)
f(NULL);     // 一般调用 f(int),也不会调用 f(void*)
f(nullptr);  // ✅ 正确调用 f(void*)

nullptr 避免了因为整型优先级导致的错误重载决议。

原因三:更明确的语义

1
2
3
auto result = findRecord(...);
if (result == 0)       // ❌ 不知道 result 是 int 还是指针
if (result == nullptr) // ✅ 明确:result 是指针类型

nullptr 让代码更具可读性和意图表达性

原因四:模板参数推导中的正确行为

模板定义:

1
2
3
4
5
template<typename Func, typename Mutex, typename Ptr>
auto lockAndCall(Func func, Mutex& mtx, Ptr ptr) -> decltype(func(ptr)) {
    std::lock_guard<Mutex> g(mtx);
    return func(ptr);
}

三种调用:

1
2
3
lockAndCall(f1, m1, 0);         // ❌ 0 推导为 int,类型错误
lockAndCall(f2, m2, NULL);      // ❌ NULL 也被推导为整型,类型错误
lockAndCall(f3, m3, nullptr);   // ✅ 推导为 std::nullptr_t,可转换为任意指针

nullptr模板友好型空指针常量,不会因类型推导错误导致编译失败。

nullptr 的类型特性

  • 类型:std::nullptr_t
  • 隐式转换为任意指针类型
  • 不能转换为整数类型,因此不会误选 int 重载版本

总结

推荐:

  • 使用 nullptr 表示空指针。
  • 尤其在函数重载、模板调用、自动类型推导 (auto) 场景下。

避免:

  • 0NULL 表示空指针:容易误选重载、类型推导错误。
  • 同时重载 intpointer 类型时传入 0/NULL
本文由作者按照 CC BY 4.0 进行授权