假设我们有一个流,其中只包含:
hello
请注意,\n最后没有像文本文件中那样的额外内容。现在,以下简单代码显示eof在提取单个std::string.
int main(int argc, const char* argv[])
{
std::stringstream ss("hello");
std::string result;
ss >> result;
std::cout << ss.eof() << std::endl; // Outputs 1
return 0;
}
但是,我不明白为什么根据标准会发生这种情况(我正在阅读 C++11 - ISO/IEC 14882:2011(E))。operator>>(basic_stream<...>&, basic_string<...>&)被定义为表现得像一个格式化的输入函数。这意味着它构造了一个sentry对象,该对象继续吃掉空白字符。在这个例子中,没有,所以sentry构造完成没有问题。当转换为 abool时,sentry对象给出true,因此提取器继续进行字符串的实际提取。
然后将提取定义为:
提取并附加字符,直到发生以下任何情况:
n存储字符;- 文件结束出现在输入序列上;
isspace(c,is.getloc())对于下一个可用的输入字符c为真。提取最后一个字符(如果有)后,调用 is.width(0) 并销毁哨兵对象 k。如果函数没有提取字符,它会调用
is.setstate(ios::failbit),这可能会抛出ios_base::failure(27.5.5.4)。
这里实际上没有任何东西会导致该eof位被设置。是的,如果到达文件末尾,提取将停止,但它不会设置该位。实际上,eof只有在执行 another 时才应设置该位ss >> result;,因为当sentry尝试吞噬空白时,会发生以下情况:
如果
is.rdbuf()->sbumpc()或is.rdbuf()->sgetc()返回traits::eof(),函数调用setstate(failbit | eofbit)
但是,这肯定还没有发生,因为尚未failbit设置。
设置该位的结果是,在读取文件时邪恶习语不起作用eof的唯一原因是因为最后的额外内容,而不是因为该位尚未设置。当提取在文件末尾停止时,我的编译器很乐意设置该位。while (!stream.eof())\neofeof
那么这应该发生吗?还是标准的意思是说setstate(eofbit)应该发生?
为了使它更容易,标准的相关部分是:
- 21.4.8.9 插入器和提取器 [string.io]
- 27.7.2.2 格式化输入函数 [istream.formatted]
- 27.7.2.1.3 类
basic_istream::sentry[istream::sentry]