nullptr虚假吗?

时间:2019-08-16 15:19:33

标签: c++ c++11 implicit-conversion nullptr

当用作布尔表达式或显式或隐式转换为布尔值时,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

3 个答案:

答案 0 :(得分:18)

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

  

1指针文字是关键字nullptr。它是类型的prvalue   std :: nullptr_t。 [注意: std :: nullptr_t是一种独特的类型,它是   既不是指针类型也不是成员指针类型;而是一个prvalue   此类型是空指针常量,可以将其转换为   空指针值或空成员指针值。参见7.11和7.12。 -   结束语]

和(7次标准转化)

  

4某些语言构造要求将表达式转换   为布尔值。 在这种情况下出现的表达式e是   据说可以根据上下文转换为bool,并且如果且   仅当声明bool t(e)时;格式良好,对于某些发明   临时变量t(11.6)。

最后(7.14布尔转换)

  

1算术,无作用域枚举,指针或   指向成员的指针类型可以转换为bool类型的prvalue。一种   零值,空指针值或空成员指针值是   转换为假;其他任何值都将转换为true。 对于   直接初始化(11.6),类型为std :: nullptr_t的prvalue可以是   转换为bool类型的prvalue;结果值为false。

那是你可能写的例子

bool b( nullptr );

但是您可能不会写(尽管某些编译器存在与此相关的错误)

bool b = nullptr;

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

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

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

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

  

9 逻辑否定运算符的操作数!在上下文中   转换为bool (第7条);如果转换后的值是true   操作数为false,否则为false。结果类型为bool

因此,该表达式中的nullptr不会转换为指针。它会根据上下文直接转换为bool。

答案 1 :(得分:5)

保证您的代码结果[dcl.init]/17.8

  

否则,如果初始化是直接初始化,则源类型为std​::​nullptr_­t,而目标类型为bool,则被初始化对象的初始值为false。 / p>

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

使用false作为nullptr的条件或if的操作数时,它被认为是contextual conversions

  

如果声明operator!的格式正确,则执行隐式转换

这意味着bool t(e);if (nullptr)!nullptr都将被转换为值nullptr的{​​{1}}。

答案 2 :(得分:1)

是,但是您应该避免使用此事实。

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

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

而不是

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

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

第二个变体为读者增加了另一点困惑:x是什么?是布尔值吗?普通值(例如整数)?指针?可选的?即使x有一个有意义的名称,也不会帮您什么忙:if (!network_connection) ...它可能仍然是可以转换为整数或布尔值的复杂结构,它可能是是否有连接,它可以是指针,值或可选的。还是其他的东西。

此外,记住nullptr的计算结果为假是您需要存储在大脑后方的另一条信息,以正确解码正在读取的代码。我们可能从过去或阅读其他人的代码后就习惯了它-但是如果我们不习惯,nullptr的表现就不会那么明显。从某种意义上说,它与其他晦涩的保证(如the value at index 0 of an empty std::string is guaranteed to be \0)并没有什么不同。除非绝对必要,否则不要让您的代码依赖于此。


PS:如今,实际上空指针的使用已经大大减少了。如果不需要,您可以force pointer to never be null;您可以使用引用代替指针;并且您可以使用std::optional<T>返回T或“ no T”。也许您可以避免完全提及nullptr