-->

What did the author mean with his comment about th

2019-09-08 19:21发布

问题:

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 argument a is changed if everything went well.

I failed to understand the phrase emphasized above.

回答1:

If s >> c fails then c is not written to.

If c was uninitialized , it remains uninitialized at the point of the test if( c == '(' ). Reading an uninitialized char 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 if s is not good(). This is OK, although IMHO it would be clearer to write:

char c;
s >> c;

if ( !s )
    return s;

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.



回答2:

Consider what happens if we didn't initialize c:

char c;
s >> c;
if (c == '(') { ... }

We are not checking to see if >> succeeded or failed. So if c == '(', it could be for one of two reasons:

  1. The >> succeeded and we retrieved the character '(' from the istream.
  2. The >> failed, but the random byte that happened to be in the memory for c when it was created is a '('.

If you initialize c to 0, case 2 is impossible: if the operation failed, we know that c will be 0... so we will know for sure that if we got a '(' it's because it came from the istream.



标签: c++ istream