This is an example extracted from section 10.3.3 Input of User-defined Types from the book "The C++ Programming Language" second edition, by B. Stroustrup. The code is old but still compiles with minor changes. Example:
#include <istream> #include <complex> using namespace std; istream& operator>>(istream& s, complex<double>& a) { // input formats for a complex; "f" indicates a float: // // f // (f) // (f, f) double re = 0, im = 0; char c = 0; s >> c; if( c == '(' ) { s >> re >> c; if( c == ',' ) s >> im >> c; if( c != ')' ) s.clear(ios::badbit); // set state } else { s.putback(c); s >> re; } if( s ) a = complex<double>(re, im); return s; }
Despite the scarcity of error-handling code, this will actually handle most kinds of errors. The local variable
c
is initilized to avoid having its value accidentally'('
after a failed operation. The final check of the stream state ensures that the value of the argumenta
is changed if everything went well.
I failed to understand the phrase emphasized above.
Consider what happens if we didn't initialize
c
:We are not checking to see if
>>
succeeded or failed. So ifc == '('
, it could be for one of two reasons:>>
succeeded and we retrieved the character'('
from theistream
.>>
failed, but the random byte that happened to be in the memory forc
when it was created is a'('
.If you initialize
c
to0
, case 2 is impossible: if the operation failed, we know thatc
will be0
... so we will know for sure that if we got a'('
it's because it came from theistream
.If
s >> c
fails thenc
is not written to.If
c
was uninitialized , it remains uninitialized at the point of the testif( c == '(' )
. Reading an uninitializedchar
causes undefined behaviour.The author is talking about a possible way that this undefined behaviour might manifest itself.
The suggested fix of
char c = 0;
relies on the fact thats.putback(c);
does nothing ifs
is notgood()
. This is OK, although IMHO it would be clearer to write:Then anybody reading the code can immediately see that it behaves properly in case of error; instead of having to thread their way through the flow of the function and check that no other operations will do anything unexpected.