Sample code:
#include
int main()
{
int x = 5;
std::cin >> x;
std::cout << x << \'\\n\';
}
On on
According to 27.7.2.2.1 [istream.formatted.reqmts] paragraph 1 the first things for the formatted input function is to construct an std::istream::senty
object. Further processing depends on whether this object converts to true
or false
: nothing happens to the value if the sentry
converts to false
.
According to 27.7.2.1.3 [istream::sentry] paragraphs 5 and 7 the sentry
will convert to false
if the stream's flags are not std::ios_base::goodbit
. That is, if either a failure happend or EOF is reached the sentry
will convert to false
. As a result, the value
stays at 5
when EOF is reached after skipping whitespace, assuming std::ios_base::skipws
is set. Unsetting std::ios_base::skipws
should result in the value becoming 0
if there is, at least, one space.
Once parsing is actually done, the applies logic is defined in 22.4.2.1.2 [facet.num.get.virtuals] paragraph 3, Stage 3. The key section on the affected value is
...
The numeric value to be stored can be one of:
— zero, if the conversion function fails to convert the entire field.
ios_base::failbit
is assigned toerr
.— the most positive representable value, if the field represents a value too large positive to be represented in
val
.ios_base::failbit
is assigned toerr
.— the most negative representable value or zero for an unsigned integer type, if the field represents a value too large negative to be represented in
val
.ios_base::failbit
is assigned toerr
.— the converted value, otherwise.
The resultant numeric value is stored in
val
.
So, the observed behavior is correct.
With pre-C++11 the value was left unchanged in all cases. It was considered desirable to tell errors apart and indicate with the value which value should be represented. The discussions on how to change the behavior went on for a rather long time and were actually quite contentious.
That the value isn't changed if EOF is reached before attempting a conversion may be considered an error. I don't recall that case to be considered while the change was discussed.
Yes, this is the correct behaviour since C++11.
The difference in what you're seeing is that a zero is written "when extraction fails", but extraction is not even attempted if EOF is already set on the stream… so nothing happens.