为什么"bool c = nullptr ;"编译 (C++11)?



我不明白为什么以下代码编译?

int main()
{
//int a = nullptr;  // Doesn't Compile
//char b = nullptr; // Doesn't Compile
bool c = nullptr; // Compiles
return 0;
}

而评论部分则没有。


我已经经历了这个和这个。

boolnullptr都是关键字,那么其他数据类型有什么独特之处呢?

出于与

if( p ) { ... }

编译:基本类型的任何值都隐式转换为布尔值,0转换为false,任何其他值转换为true

最初,基本类型值必须转换为bool以实现 C 兼容性。C 最初没有bool类型,但任何数值表达式都可以用作布尔值(使用 0 ==false约定)。现在我们陷入了向后兼容性的纠结。nullptr必须支持惯用构造,例如if(p),特别是对于旧代码的文字0NULL被替换为nullptr的情况。例如,像if(p)这样的代码可以来自宏扩展或模板代码。


附录:为什么nullptr不转换为例如int.

由于nullptr隐式转换为bool,而bool(不幸的是)隐式转换为int,因此可以预期nullptr也应该转换为int。但nullptr的要点是它应该表现为指针值。虽然指针确实隐式转换为bool,但它们不会隐式转换为数值类型。

但是,为用户定义类型安排此类限制并不完全简单。如果存在operator bool转换,将调用转换为int。一个 C++11 解决方案来预测限制,是使转换运算符成为受std::enable_if限制的模板,如下所示:

#include <type_traits>  // std::enable_if, std::is_same
struct S
{
template< class Type >
operator Type* () const { return 0; }
template<
class Bool_type,
class Enabled = typename std::enable_if<
std::is_same<Bool_type, bool>::value, void
>::type
>
operator Bool_type () const { return false; }
};
auto main() -> int
{
bool const              b   = S();      // OK.
double const*  const    p   = S();      // OK.
int const               i   = S();      // !Doesn't compile.
}

C++11 §4.12布尔转换

算术、无作用域枚举、指针或指向成员类型的指针的 prvalue 可以转换为类型bool的 prvalue。零值、空指针值或空成员指针值将转换为false;任何其他值都将转换为truestd::nullptr_t类型的 prvalue 可以转换为bool类型的 prvalue ;结果值为false

确实,nullptr是一个关键字,但它是一个空指针文字,与bool的角色不同。想想布尔文字,truefalse也是关键字。

在 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#654 中,杰森·梅里尔认为

我们可以用任意指针做的任何事情,我们也应该能够用nullptr_t做。

我认为以下(有点人为的)示例支持该论点(尽管我不完全确定它是否适用于这种情况)

template<typename T, typename P>
void safeProcess(T pointer, P &processor) {
bool isNonNull(pointer);
if(isNonNull) {
processor.process(pointer);
}
}

这将允许传递nullptrprocessor.process接受的任何指针兼容的其他指针类型。

C++11 通过引入一个新关键字作为可分辨的空指针常量来更正此问题:nullptr。它属于 nullptr_t 类型,它是隐式可转换的,可与任何指针类型或指向成员的指针类型相媲美。它不是隐式可转换的,也不是与积分类型相当的,除了布尔值。虽然最初的提案指定 nullptr 类型的右值不应转换为布尔值,但核心语言工作组决定,为了与常规指针类型保持一致,这种转换是可取的。2008年6月,对拟议的措辞修改一致表决通过工作文件。[2]

出于向后兼容性的原因,0 仍然是有效的空指针常量。

char *pc = nullptr;     // OK
int  *pi = nullptr;     // OK
bool   b = nullptr;     // OK. b is false.
int    i = nullptr;     // error

最新更新