为什么在空流上调用时 std::istream::ignore 而不是 return?

Why does std::istream::ignore not return when called on an empty stream?

std::cin 是一个全局对象,因此我总是想在使用它之前将其设置为良好状态。但是,当在未使用的 cin 上调用 ignore() 时,该函数不会 return。

参见下面的示例代码。如果没有用户干预,执行不会到达第 8 行 (cout)。在我的测试中,此行为与第二个参数(定界符,我试过 '\n' 和 EOF)一致或不一致。

我查阅了一些在线参考资料,但我不明白为什么会这样。

#include <limits>
#include <iostream>
#include <string>
std::string readInput() {
    std::string input = "";
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cout << "We never get here..." << std::endl;
    std::getline(std::cin, input);
    return input;
}
int main() {    
    std::string foo = readInput();  
}
  1. 为什么在这种情况下 ignore() 而不是 return?
  2. 如何在使用前安全地重置和清空std::cin

参见第二个参数 '\n'。您请求 读取 '\n' 之前的字符并忽略它们。由于流中没有 '\n',这意味着阻塞直到收到一个。

希望您清楚,只有在知道流中有 '\n' 时才应进行此调用。

那么,你第二个问题的答案是,在使用之前,什么都不做,因为反正流上没有数据。

清除流的时间是从流中读取一些数据之后;然后根据你使用的读操作,你会知道是否有换行符。

注意没有这个操作"clear whatever is on the stream"(这是故意设计的)。相反,您的操作将类似于 "clear the remainder of the line",其中 "the line" 被定义为直到下一个换行符;并且输入将来自使用行的文件或用户按 Enter 的交互式终端。

documentation 中所述:

ignore behaves as an UnformattedInputFunction. After constructing and checking the sentry object, it extracts characters from the stream and discards them until any one of the following conditions occurs: [...] the next available character c in the input sequence is delim, as determined by Traits::eq_int_type(Traits::to_int_type(c), delim). The delimiter character is extracted and discarded. This test is disabled if delim is Traits::eof()

因此,如果流为空,它将触发对相应流缓冲区的 underflow() 的调用,因为在您的情况下忽略正在等待 '\n'。

注意:当您想确保您的流缓冲区完全为空时,您可以调用 cin.rdbuf()->in_avail() 来获取仍在等待提取的字符数量来自输入缓冲区,因此如果缓冲区为空则为 0。然而,这高度依赖于实现,因为它可以工作,例如Visual Studio 开箱即用。另一方面,对于 GCC,您必须先调用 cin.sync_with_stdio(false) 才能拥有内部缓冲。不过,它不会像这样与 LLVM 一起工作。