当用作布尔表达式或显式或隐式转换为布尔值时,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
答案 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)
比较指向false
或0
的指针是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
。