C++ Gotchas: Errata

I'm always interested to hear of any errors or typos in the book.  Before sending a report or comment, please check the list of known errors and typos below to make sure that it has not been previously reported.  If it doesn't already appear, then I'd appreciate your reporting it to gotchas@semantics.org.

Errata for the second printing:

Errors

tb, 5/3/04
Gotcha #14, p. 40
The claim concerning the only common use of the comma operator is incorrect.  Another common use is in the initialization part of a for-statement, as in:

  
    for( i = 0, j = MAX; i <= j; ++i, --j )

The first comma is a use of a comma operator.  Ordinarily we would prefer to use a declaration in the initialization part, as in:

    for(int i = 0, j = MAX; i <= j; ++i, --j )

which would make the first comma a separator in a declaration rather than an operator.  However, sometimes the first form can be preferable, as in:

    int    i;
    float* val;
    for (i = 0, val = &(values[i]); i < numValues; ++i, ++val)

kh, 3/8/03
  [also in first printing]
Gotcha #19, p. 51
While there is no difference in meaning between new String and new String(), section 5.3.4/15 of the standard does note that there is a difference for scalar types, where the first form will result in an indeterminate value for the allocated object, and the second form will result in a zero initial value.

jsg, 5/30/06 [also in first printing]
Gotcha #62, p. 173
The implementation of overloaded operator new has a potential integer overflow in the for loop "for( int i = 0; i < n; ++i )" because i is a signed int and n is a size_t One solution is to redeclare i as a size_t.

scd, 11/8/02 [also in first printing]
Gotcha #69, p. 203-204
The statement on page 204 that the order in which the static message type objects are initialized is immaterial is correct.  However, the Firewall Monostate on page 203 implements its container of message type pointers as a static data member, and this must be initialized before insertion of any pointers to static message type objects.  One correct implementation is to use a "lazy initialization" of the container just prior to the first insertion of a message type pointer.  This is the implementation used in the downloadable code.

fv, 2/21/03  [also in first printing]
Gotcha #87, p. 265, 266
On page 266, the expression ++++j is "legal," but its behavior is undefined because the value of j is accessed and set more than once without an intervening sequence point.  On page 266, the expressions ++a = 10 and ++++a suffer from the same problem.  While the text of the gotcha is still "correct" in a strict legal sense, the undefined nature of the expressions should have been pointed out.


Typos

tb, 5/3/04
Gotcha #14, p. 40
The sentence "This author of this code needs more socialization" should begin with "The" instead of "This".


tb, 5/3/04
Gotcha #23, p. 57
There should be no space before the colon in the phrase "offers a clear

advantage :".

jf, 1/9/04
Gotcha #42, p. 109
I state that "An IsEven object has no data members, no virtual functions, and no constructor or destructor."  I should have been more precise, and said "Because a
n IsEven object has no data members and no virtual functions, it has no non-trivial constructors, destructor, or copy assignment."

tb, 5/6/04
Gotcha #43, p. 110
In the last line of text, the first word of the parenthetical phrase "as least during testing" should be "at."


tb, 5/11/04
Gotcha #54, p. 148
In the second to the last prose sentence on the page, change "Suppose we add a data member..." to "What would happen if we were to add a data member..."

tb, 5/11/04
Gotcha #55, p. 150-151
The parenthetical sentence begun at the end of page 150 is not continued on the next page.  The full sentence should read, "(Atranslation unit is basically a preprocessed file.)"


tb, 5/12/04
Gotcha #65, p. 181
The sentence near the middle of the page that begins
"Here, the storage to which..." does not parse.  The sentence should read, "Here, the storage to which the pointer exception object is referring may no longer exist when the exception is caught."

tb, 5/14/04
Gotcha #66, p. 187
The last code example on this page should not havea gray background, since it illustrates correct code.


Errata for the first printing:

Errors

kh, 3/8/03
Gotcha #19, p. 51
While there is no difference in meaning between new String and new String(), section 5.3.4/15 of the standard does note that there is a difference for scalar types, where the first form will result in an indeterminate value for the allocated object, and the second form will result in a zero initial value.

sb, 6/17/03
Gotcha #53, p. 145-146
Inexplicably, the argument to the base class assignment operator is *this rather than rhs.  As a result the assignment would (presumably) change only the derived class portion of the object.
The correct implementation of the assignment on page 145 is
D &D::operator =( const D &rhs ) {
    if( this != &rhs ) {
        B::operator =(rhs);
        C::operator =(rhs);
        // assign any D-specific members...
    }
    return *this;
}
The correct implementation of the assignment on page 146 is
D &D::operator =( const D &rhs ) {
    if( this != &rhs ) {
        A::operator =(rhs);
        B::nonvirtassign(rhs);
        C::nonvirtassign(rhs);
        // assign any D-specific members...
    }
    return *this;
}

kh, 3/8/03
Gotcha #54, p. 149-150
The implementations of D's copy operations are not exception-safe.  They should have ensured that the new X object was successfully allocated and initialized before the old X object was deleted.

rp, 11/6/05
Gotcha #67, p. 194
The DBLock class should have prevented copying by declating its copy operations to be private and undefined.  As it stands, copies of a DBLock object may cause multiple calls to unlockDB without an intervening call to lockDB.

scd, 11/8/02
Gotcha #69, p. 203-204
The statement on page 204 that the order in which the static message type objects are initialized is immaterial is correct.  However, the Firewall Monostate on page 203 implements its container of message type pointers as a static data member, and this must be initialized before insertion of any pointers to static message type objects.  One correct implementation is to use a "lazy initialization" of the container just prior to the first insertion of a message type pointer.  This is the implementation used in the downloadable code.

fv, 2/21/03
Gotcha #87, p. 265, 266
On page 266, the expression ++++j is "legal," but its behavior is undefined because the value of j is accessed and set more than once without an intervening sequence point.  On page 266, the expressions ++a = 10 and ++++a suffer from the same problem.  While the text of the gotcha is still "correct" in a strict legal sense, the undefined nature of the expressions should have been pointed out.

bww, 2/23/03
Gotcha #88, p. 270
The rendition of the equivalent of the compiler-generated copy assignment operator for the Money class should be implemented as it is below, not as it is on page 270.

template <Currency currency>
Money<currency> &
Money<currency>::operator =( const Money &rhs ) {
    myCurve_ = rhs.myCurve_; // leak, alias and change of curve!
    amt_ = rhs.amt_;
}


Typos

scd, 11/30/02
Gotcha #7, p. 18
The Postorder::next function implements an external, not internal, iteration.

scd, 12/2/02
Gotcha #29, p. 77
The comment on the declaration of badButton wraps around.

bb, 10/20/03
Gotcha #32, p. 83
The second and third bullet items in the quote from the standard should not start with "The."

kh, 3/8/03
Gotcha #32, p. 85
The second argument to the get_token function should be declared to be const char *, not char *.  That usage is (still) legal but deprecated.

kh, 3/8/03
Gotcha #42, p. 109
The operator () member of IsEven should be declared to be a const member function.

ms, 2/19/03
Gotcha #44, p. 112
In the first sentence of this page, the reference should be to Gotcha #5, not Gotcha #7.

kh, 3/8/03
Gotcha #60, p. 167
The use of the term "scalar" is incorrect here.  Section 3.9/10 of the standard defines "scalar" as referring to artihmetic, enum, and pointer types only.  This discussion of new and delete should have used the terms "arrays and non-arrays" rather than "arrays and scalars" so as to include class objects in the latter category.

kh, 3/8/03
Gotcha #62, p. 173
Since std::string::c_str never returns a null pointer, it is not necessary for this implementation of an overloaded operator new to check that the return value is non-null.

epn, 2/16/03
Gotcha #64, p. 178
"The principle reason..." should be "The principal reason..."  Shameful! Perhaps I meant "The principled reason..."?

ct, 6/23/03
Gotcha #79, p. 239
"As Figure 7-16 shows, the identifier B::f dominates..." should read "As Figure 7-16 shows, the identifier B1::f dominates..."


Eagle-Eyed Contributors

bb = Bruce Barr
bww = Bradley White

ct = Clovis Tondo
epn = Eric Nagler
fv = Faisal Vali
jf = Jeremy Fixemer
jsg = Jeff Gennari
kh = Kevlin Henney
ms = Mihailo Stanic
rp = Roland Pibinger
sb = Stephan Beal
scd = Steve Dewhurst, the blushing author
tb = Tim Buchowski


 
 
Copyright © 2003 by Stephen C. Dewhurst