【问题标题】:How can std::cin return a bool and itself at the same time?std::cin 如何同时返回 bool 和自身?
【发布时间】:2016-12-23 00:39:24
【问题描述】:

我正在读一本关于 C++ 的书,上面说如果我使用 >> 运算符,它会返回运算符左侧的对象,所以在这个例子中

std::cin >> value1;

代码返回std::cin

但如果我这样做

while(std::cin >> value1)

我的代码将一直在循环中,直到出现 std::cin 错误,所以这必须意味着操作员返回一个 bool,当 std::cin 没有失败时为真,当 std::cin 失败时为假。

是哪一个?

【问题讨论】:

  • std::cin 也有一个转换为bool 的运算符,用于条件。
  • @πάνταῥεῖ 评论是针对 cme​​ts,而不是答案。

标签: c++ cin


【解决方案1】:

std::cinstd::istream 类型(这只是 std::basic_istream<char>typedef

如果您看到different overloaded operator>> for basic_istream,它们都返回了对basic_istream 的引用。所以有一件事被清除了,这里的operator>> 不返回bool,而是返回“std::cin”本身。你不会看到任何operator>> 那里返回bool 值。

所以现在的问题是,它如何将std::basic_istream 转换为bool
答案是:为此目的调用了一个转换运算符

std::basic_istream 从其父 std::basic_ios 继承 operator bool()

explicit operator bool() const;

这使得将std::basic_istream 对象转换为bool 成为可能。 人们很容易怀疑它被标记为explicit(参见why is it marked explicit),但它仍然在ifwhile 中隐式转换为bool

这个问题的答案是ifwhile“隐式”使用显式转换。 (见this answer by @R. Martinho Fernandes)。所以ifwhilefor 是隐式发生这种“上下文转换”到bool 的地方之一。

【讨论】:

    【解决方案2】:

    [...] 所以这一定意味着操作符返回一个 bool [...]

    不,它返回std::cin(通过引用)。 while(std::cin >> value); 起作用的原因是因为std::istream(这是std::cin 的类型)有一个conversion operator

    转换运算符基本上允许将一个类隐式(如果它没有标记为explicit)转换为给定的类型。在这种情况下,std::istream 定义其operator bool 以返回是否发生错误(通常为failbit);

    [std::ios_base::operator bool()]

    如果流没有错误并且准备好进行 I/O 操作,则返回 true。具体来说,返回!fail()


    explicit operator bool() const;
    

    请注意,即使运算符是 explicit(它不应该允许像 if (std::cin); 这样的隐式转换),在需要 bool 的上下文中使用限定符时也会被忽略,例如 if、@987654339 @ 循环和for 循环。不过,这些都是例外,而不是规则。

    这是一个例子:

    if (std::cin >> value);  //OK, a 'std::istream' can be converted into a 'bool', which 
                             //therefore happens implicitly, without the need to cast it: 
    
    if (static_cast<bool>(std::cin >> value)); //Unnecessary
    
    bool b = std::cin >> value;  //Error!! 'operator bool' is marked explicit (see above), so 
                                 //we have to call it explicitly:
    
    bool b = static_cast<bool>(std::cin >> value); //OK, 'operator bool' is called explicitly
    

    【讨论】:

    • 如果您指出一个简单的void* ptr = NULL: if (ptr) 也可以工作(他或她肯定熟悉),这可能不会让 OP 感到困惑,因为它是 convertibility bool 这很重要,而不是具有 bool 类型的实际表达式。
    • @LightnessRacesinOrbit 好主意 :) 但是没有 `void* 可能会更好,应该避免它。
    • 我认为除了规则中的例外之外,添加一个像bool good=std::cin; 这样的非例外是有用的,它不能编译。
    • @Ruslan 好主意 :)
    • 很好的解释。与其完全描述“异常”,不如说将任何表达式放在ifwhile 条件中相当显式地转换为bool。
    【解决方案3】:

    对流的操作返回对流的引用。

    所以,不是bool

    您可以将结果粘贴到if 条件中,原因与您可以这样做的原因相同:

    void* ptr = foo();
    if (ptr) { /*...*/ }
    

    而且,就此而言,这是:

    int x = foo();
    if (x) { /*...*/ }
    

    这里的ptrx 都可以转换bool 以用于条件。对于std::cin,转换是通过std::ostream 类中的operator bool() 实现的,该类是为这个确切的任务明确(双关语)添加的。

    【讨论】:

      【解决方案4】:

      std::istreamstd::cin 是其对象的类)具有以下成员函数:

      explicit operator bool() const;
      

      如果对象处于错误状态,则返回 false,否则返回 true。这就是while(std::cin &gt;&gt; value1) 构造起作用的原因。在 C++11 之前,它有这个非显式函数:

      operator void*() const;
      

      如果对象处于错误状态,则返回一个空指针,用于相同的目的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-10
        • 2020-03-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多