РЕДАКТИРОВАТЬ : Это происходило из-за того, как старые версии libc ++ интерпретировали стандарт C ++.Интерпретация обсуждалась в выпуск LWG 2036 , она была признана неверной и libc ++ была изменена.
Текущий libc ++ дает в вашем тесте те же результаты, что и libstdc ++.
старый ответ:
Ваше понимание верно.
istream::get()
выполняет следующее:
- Вызывает
good()
и устанавливает failbit
, если возвращается false(это добавляет бит в поток, в котором был установлен какой-то другой бит), (§27.7.2.1.2[istream::sentry]/2
) - Сбрасывает все, что связано (), если необходимо,
- Если
good()
является ложным в этомpoint, возвращает eof и больше ничего не делает. - Извлекает символ , как если бы , вызывая
rdbuf()->sbumpc()
или rdbuf()->sgetc()
(§27.7.2.1[istream]/2
) - Если
sbumpc()
или sgetc()
возвращает eof, устанавливает eofbit
.(§27.7.2.1[istream]/3
) и 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.
Ваш тестовый сценарий выдает мне тот же вывод, используя последние версии обеих библиотек.