EDIT:这是由于旧版本的 libc++ 解释 C++ 标准的方式造成的。对此解释进行了讨论LWG 2036 期 http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#2036,被判定为不正确,并更改了 libc++。
当前的 libc++ 在测试中给出的结果与 libstdc++ 相同。
旧答案:
你的理解是正确的。
istream::get()
执行以下操作:
- Calls
good()
,并设置failbit
如果它返回 false(这会向设置了其他位的流添加一个故障位),(§27.7.2.1.2[istream::sentry]/2
)
- 如有必要,刷新任何绑定的东西
- If
good()
此时为 false,返回 eof 且不执行任何其他操作。
- 提取一个字符as if通过致电
rdbuf()->sbumpc()
or rdbuf()->sgetc()
(§27.7.2.1[istream]/2
)
- If
sbumpc()
or sgetc()
返回eof,集合eofbit
. (§27.7.2.1[istream]/3
) and failbit
(§27.7.2.2.3[istream.unformatted]/4
)
- 如果抛出异常,则设置 badbit (
§27.7.2.2.3[istream.unformatted]/1
) 并在允许的情况下重新抛出。
- 更新 gcount 并返回字符(如果无法获取则返回 eof)。
(引用自 C++11 的章节,但 C++03 在第 §27.6.* 下具有所有相同的规则)
现在我们来看看具体的实现:
libc++(当前 svn 版本)将 get() 的相关部分定义为
sentry __s(*this, true);
if (__s)
{
__r = this->rdbuf()->sbumpc();
if (traits_type::eq_int_type(__r, traits_type::eof()))
this->setstate(ios_base::failbit | ios_base::eofbit);
else
__gc_ = 1;
}
libstdc++(随 gcc 4.6.2 一起提供)定义了与
sentry __cerb(*this, true);
if (__cerb)
{
__try
{
__c = this->rdbuf()->sbumpc();
// 27.6.1.1 paragraph 3
if (!traits_type::eq_int_type(__c, __eof))
_M_gcount = 1;
else
__err |= ios_base::eofbit;
}
[...]
if (!_M_gcount)
__err |= ios_base::failbit;
如您所见,两个库都调用sbumpc()
并设置 eofbit 当且仅当 sbumpc() 返回 eof 时。
您的测试用例使用两个库的最新版本为我生成相同的输出。