【问题标题】:Why "bool c = nullptr ;" compiles (C++11)?为什么“bool c = nullptr;”编译(C++ 11)?
【发布时间】:2014-03-27 14:24:14
【问题描述】:

我不明白为什么要遵循代码compiles

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

       return 0;
}

而评论部分没有。


我已经浏览过thisthis

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

【问题讨论】:

  • “bool 和 nullptr 都是关键字,那么其他数据类型的独特之处是什么?” 如果您能澄清为什么它们都是关键字这一事实会使我很高兴一个区别。如果你说std::nullptr_t p; int a = p; bool c = p; 对你有影响吗?
  • @JohannesSchaub-litb 很抱歉造成混淆,但我担心的是为什么nullptr 不能转换为基本数据类型,即charint
  • 问题和答案适用于 C++11,但对于任何更高版本的语言规范来说已经过时了。自 C++14 以来,NOT 中的这种隐式转换不再允许直接初始化上下文之外。上面的初始化NOT编译。

标签: c++ pointers c++11 null-pointer


【解决方案1】:

出于同样的原因

if( p ) { ... }

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

为了 C 兼容性,最初的基本类型值必须转换为 bool。 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.
}

【讨论】:

  • 我不明白为什么这提供了原因。 p 不是空指针常量。为什么要直接写if(nullptr) { ... }
  • 我确实看到了将指针转换为 bool(甚至与 C 兼容性无关)以及整数(为了 C 兼容性)的明显需求。但是nullptrnullptr_t 是C++ 独有的,所以我不太明白这里的原因(这就是我以这种方式制定第一条评论的原因)。
  • 技术上 nullptr_t 不需要转换为 bool。这会有点奇怪,因为if (nullptr) 将无法编译,而if( ptr = nullptr ) 将编译,但是...... 然而 如果你编写了一个 template 函数,其中一个参数是指针-like,能够通过nullptr 会很好,然后会出现if 子句。
  • 希望if( ptr = nullptr )给出警告。
  • @Cheersandhth.-Alf 在if 中的分配会生成一个死分支(或重言式if经常表明使用了=而不是==
【解决方案2】:

C++11 §4.12 布尔转换

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

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

【讨论】:

  • 这个答案没有进入规则的基本原理,即 OP 要求的“为什么”。 IE。它甚至不是一个答案。但是,它并没有错。
  • @Cheersandhth.-Alf 我回答了两件事: 为什么nullptr 可以转换为bool。 为什么它可以在语法上用在= 的右侧,而显然你不能把bool(这也是一个关键字)放在那里。因为nullptr 是文字,就像42true(另一个关键字是文字)一样。也许我们对OP主要要求的内容有不同的看法,但我认为我的回答至少回答了OP的一些问题。
  • 嗯,正如我所见,,“为什么”,没有得到回答。但是 ,关于类型与值的混淆,可能正是 OP 曾经/正在询问的内容。我没看到,抱歉。
  • 由于提问者没有指定他的编译器,很可能是他的“为什么“bool c = nullptr;” compiles” 并不是“为什么我的编译器会接受这个?让客户满意?只是合规?” (您的回答“因为标准要求 ”确实会回答),但问题可能是“为什么标准在某处要求这个?”,您根本没有回答。而且我不明白“......但它是一个空指针文字,与布尔的作用不同”的意思。如果你能澄清那部分,我会很高兴。
  • @JohannesSchaub-litb 我没有回答这个问题,因为我一开始并不认为这是主要问题,但是在@Cheers 和hth 之后。 - 阿尔夫更新了他的答案,我认为我不能提供比他的答案更好的答案。我在强调nullptrbool不是同一种关键字,它的作用是指针类型的文字,就像true对于bool类型一样,但是正如我刚刚看到OP的评论,这不是什么他主要是问。如果我能想到@Alf 和您的答案的不同观点,我肯定会更新我的答案以更好地适应 OP 的明确问题。
【解决方案3】:

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#654 中,Jason Merril 争辩说

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

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

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

这将允许传递 nullptr 以及与 processor.process 接受的任何内容兼容的其他指针类型。

【讨论】:

    【解决方案4】:

    C++11 通过引入一个新的关键字来作为一个可区分的空指针常量来纠正这个问题:nullptr。它是 nullptr_t 类型,可隐式转换并与任何指针类型或指向成员的指针类型相当。除了 bool 之外,它不能隐式转换或与整数类型相比较。虽然最初的提案规定 nullptr 类型的右值不应转换为 bool,但核心语言工作组认为这种转换是可取的,以与常规指针类型保持一致。提议的措辞更改于 2008 年 6 月被一致投票纳入工作文件。[2]

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-07
      • 1970-01-01
      • 1970-01-01
      • 2018-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多