nullptr 是假的吗?

Is nullptr falsy?

当用作布尔表达式或显式或隐式转换为布尔值时,nullptr 是否始终为假?此实现是否在标准中定义或指定?

我写了一些代码来测试,但不确定它是否完全测试了 属性。我找不到专门讨论这个问题的现有 SO 答案。 cppreference据我所知没有提到这个。

if (nullptr) {
    ;
} else {
    std::cout << "Evaluates to false implicitly\n";
}

if (!nullptr) {
    std::cout << "Evaluates to false if operated on\n";
}

if (!(bool)(nullptr)) {
    std::cout << "Evaluates to false if explicitly cast to bool\n";
}

预期和实际:

Evaluates to false implicitly
Evaluates to false if operated on
Evaluates to false if explicitly cast to bool

你的代码的结果是有保证的,[dcl.init]/17.8

Otherwise, if the initialization is direct-initialization, the source type is std​::​nullptr_­t, and the destination type is bool, the initial value of the object being initialized is false.

这意味着,对于直接初始化,bool 对象可以从 nullptr 初始化,结果值为 false。然后对于 (bool)(nullptr)nullptr 转换为 bool,值为 false

nullptr作为if的条件或operator!的操作数时,被认为是contextual conversions

the implicit conversion is performed if the declaration bool t(e); is well-formed

也就是说,if (nullptr)!nullptrnullptr都会被转换成bool,值为false

根据 C++ 17 标准(5.13.7 指针文字)

1 The pointer literal is the keyword nullptr. It is a prvalue of type std::nullptr_t. [ Note: std::nullptr_t is a distinct type that is neither a pointer type nor a pointer-to-member type; rather, a prvalue of this type is a null pointer constant and can be converted to a null pointer value or null member pointer value. See 7.11 and 7.12. — end note ]

和(7 个标准转换)

4 Certain language constructs require that an expression be converted to a Boolean value. An expression e appearing in such a context is said to be contextually converted to bool and is well-formed if and only if the declaration bool t(e); is well-formed, for some invented temporary variable t (11.6).

最后(7.14 布尔转换)

1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer-to-member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. For direct-initialization (11.6), a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.

也就是你可以这样写

bool b( nullptr );

但你可能不会写(尽管一些编译器有一个与此相关的错误)

bool b = nullptr;

因此 nullptr 可以根据上下文转换为 bool 类型的对象,例如在 if 语句等选择语句中。

让我们考虑例如 if 语句中的一元运算符 !

if ( !nullptr ) { /*...*/ }

根据运算符的描述(8.5.2.1 一元运算符)

9 The operand of the logical negation operator ! is contextually converted to bool (Clause 7); its value is true if the converted operand is false and false otherwise. The type of the result is bool

所以这个表达式中的nullptr没有转换为指针。它直接根据上下文转换为 bool.

是的,但你应该避免使用这个事实。

比较指向 false0 的指针是 C/C++ 编码中的常见比喻。我建议您避免使用它。如果要检查是否为空,请使用:

if (x == nullptr) { /* ... */}

而不是

if (!x) { /* ... */}

if (not x) { /* ... */}

第二个变体为reader增加了一点混乱:什么是x?它是布尔值吗?普通值(例如整数)?指针?一个可选的?即使 x 有一个有意义的名字,它也不会对你有多大帮助: if (!network_connection) ...它仍然可以是一个复杂的结构,可以转换为一个整数或一个布尔值,它可能是一个布尔指示符无论是否存在连接,它都可以是一个指针、一个值或一个可选的。或者别的。

此外,记住 nullptr 的计算结果为 false 是您需要存储在大脑后部的另一位信息,以正确解码您正在阅读的代码。我们可能从过去或阅读其他人的代码时就习惯了它 - 但如果我们不习惯,那么 nullptr 的行为就不会很明显。从某种意义上说,它与其他晦涩的保证并没有什么不同,比如。除非绝对必要,否则不要让你的代码依赖这些东西。


PS : 现在空指针的使用实际上少了很多。如果他们不需要,你可以 force pointers to never be null;您可以使用引用而不是指针;您可以使用 std::optional<T> 到 return T 或“无 T”。也许你可以完全避免提及 nullptr