"std::cin>>value" 如何在 while 循环中求值?

How is "std::cin>>value" evaluated in a while loop?

目前正在自学C++ Primer 5th。这里有一些我不确定的东西。 (我在 F.A.Q 上找不到确切的相关问题)。

考虑这个 while 循环:

while(std::cin>>value){...}  \value here was defined as int. 

教科书说:

That expression reads the next number from the standard input and stores that number in value. The input operator (§ 1.2, p. 8) returns its left operand, which in this case is std::cin. This condition, therefore, tests std::cin.When we use an istream as a condition, the effect is to test the state of the stream. If the stream is valid—that is, if the stream hasn’t encountered an error—then the test succeeds.

我的问题是:std::cin 是先将输入读入 value 然后测试 std::cin 的有效性,还是先测试 std::cin 然后决定是否读入 'value'?我很困惑什么时候 "returns its left operand".

有两个测试。

第一个测试是while语句的条件

while(std::cin>>value){...}

此条件测试调用运算符函数的结果operator >>

第二个测试是运算符中的一个条件。如果流 std::cin 的状态良好,则该函数会尝试从字符串中读取一个整数。否则它 returns std::cin 当前错误状态 std::cin.

while条件中有一个表达式

std::cin>>value

必须对该表达式求值。所以这个条件测试 operator >> .

的调用结果

运算符的结果是流std::cin但是由于运算符

它可以根据上下文转换为bool值
explicit operator bool() const;

哪个returns流的状态

!fail().

运算符首先读取值,然后 returns 对象的引用。 while 语句首先调用该运算符,然后测试返回值。

请记住,您的代码等同于:

while (std::cin.operator>>(value)) { }

或者:

while (1) {
    std::cin >> value ;
    if (!std::cin) break ;
}

"code" 在测试 std::cin 之前总是尝试从 std::cin 读取到 value

让我们看看报价:

[...] The input operator (§ 1.2, p. 8) returns its left operand, which in this case is std::cin. [...]

这仅表示std::cin.operator>>(value) return std::cin.

This condition, therefore, tests std::cin. When we use an istream as a condition, the effect is to test the state of the stream. If the stream is valid—that is, if the stream hasn’t encountered an error—then the test succeeds.

教科书上说的是在尝试读取从std::cinvalue的整数后,>>运算符returns std::cin。如果std::cin读取value后状态良好,则测试通过,否则失败。


一些额外的细节:

std::cin >> value的时候,基本就是调用istream::operator>>(int&),而里面有一个测试该方法:如果测试通过,则 std::cin 的内部状态设置为 ios_base::goodbit, if it fails, internal state is set to on of the error flag (eofbit, failbit or badbit)。

取决于exception mask for std::cin, if the internal test fails, an exception may be thrown

来自您的引述:

When we use an istream as a condition, the effect is to test the state of the stream.

这基本上意味着:

if (std::cin) { }

equivalent到:

if (!std::cin.fail()) { }

std::cin.fail() 检查 failbitbadbit。这意味着 while (std::cin >> value) { } 不会测试 eofbit 标志,并且只会在输入无法转换为整数值时失败。

does std::cin read input into value first then test the validation of std::cin, or test std::cin first then decide whether to read into 'value'

cin 首先尝试从标准输入读取 int,如果 cin 处于良好状态:如果失败,它将设置流为错误状态;无论完成的操作如何,它都会 return 流本身(即 "left operand" -- cin),这将允许您检查成功或失败。

如果您想先显式测试流的有效性,然后再尝试读取值,您可以:

while (cin && cin >> value)

但它非常多余,因为正如我告诉过你的,如果 cin 已经处于糟糕状态,它甚至不会尝试读取 value

我假设你的 "value" 例如是一个 int

  • 流尝试读取输入直到下一个空格。

  • if eof is found ... -> then the state will be set to "eof", >> will return the stream and the boolean evaluation of the stream will return假

  • 如果在读取过程中发生错误(例如I/O),状态将设置为"bad",>>将return流并且流的布尔值评估将 return false

  • 如果发现空格,则尝试将读取的字符转换为 int(上述假设)。如果失败(例如因为读取输入是:"xx" 而不是数字),流的状态将设置为 "fail"。 >> 将 return 流和流的布尔值评估将 return false

  • 如果我们在链的下游,没有找到 eof,没有发生 IO 错误(或其他),并且字符 -> int 转换成功。 >> 将 return 流和流的布尔值评估将 return 为真。

    并且您的 "value" 将包含适当的值

想必您不会对简单的函数调用感到困惑:

SomeReturnType some_function(int&);
while (some_function(value)) { ... }

以上代码将重复调用 some_function,直到函数调用的 return 值(解释为布尔值)为 false。循环中的每个步骤都会调用该函数。函数是否改变value的值由函数决定。它当然可以这样做,而且大概会这样做(但这对功能的设计者来说是个问题)。

循环while (std::cin>>value) {...}完全等价于while (std::cin.operator>>(value)) {...}。这只是对成员函数 std::stream::operator>>(int&).

的函数调用