#include <iostream>
#include <sstream>
int main() {
std::stringstream s;
s << "a";
std::cout << "EOF? " << (s.eof() ? "T" : "F") << std::endl;
std::cout << "get: " << s.get() << std::endl;
std::cout << "EOF? " << (s.eof() ? "T" : "F") << std::endl;
return 0;
}
Thor:~$ g++ test.cpp
Thor:~$ ./a.out
EOF? F
get: 97
EOF? F
Thor:~$ clang++ -std=c++0x -stdlib=libstdc++ test.cpp
Thor:~$ ./a.out
EOF? F
get: 97
EOF? F
Thor:~$ clang++ -std=c++0x -stdlib=libc++ test.cpp
Thor:~$ ./a.out
EOF? F
get: 97
EOF? T
Thor:~$ clang++ -stdlib=libc++ test.cpp
Thor:~$ ./a.out
EOF? F
get: 97
EOF? T
get
“表现为一个未格式化的输入函数。在构造了一个sentry对象之后,如果有字符可用,则提取一个字符c。”没有关于对rdbuf()->sbump()
或rdbuf()->sgetc()
调用次数的说明。虽然我通常不会期望这种情况发生,但是如果实现额外调用rdbuf()->sgetc()
并因此设置eofbit
,也没有什么不合法的。 - James Kanzeistream::get()
并不会执行此操作——它是sentry
对象构造函数的一部分。关于第三和第四点:标准要求较少限制。提取必须 as if 通过调用rdbuf()->sbumpc()
或rdbuf()->sgetc()
(这是一个错误,因为rdbuf()->sgetc()
不会提取,而rdbuf()->snextc()
和rdbuf->sgetn()
可以提取,但未被提及)。这并没有说明前瞻发生的时间和方式。 - James Kanzestreambuf
中的任何函数都是可观察行为(因为它们转发到用户定义的虚拟函数,这些函数可能会并且通常会进行系统调用)。所有实现都会在看到文件结束时设置eofbit
。如果在特定情况下get()
通常不设置它,那是因为可以实现没有任何前瞻的get()
。可以,但不必须。但标准对前瞻完全保持沉默。 - James Kanzeget()
被指定为提取一个字符,就像>> int
被指定为提取组成int
的字符一样。标准确实允许向前查看;否则,>> int
无法实现。如果istream在这个向前查看中遇到EOF,它将设置eofbit
;历史上,filebuf
的实现不一定会在第二次调用sgetc
时返回EOF。eofbit
的指定语义是“表示输入操作已达到输入序列的末尾”。如果get()
读取了最后一个字节,则为真。 - James Kanze