Exceptional C++ - Errata List

Home Blog Talks Books & Articles Training & Consulting

Up
Next

On the
blog
RSS feed November 4: Other Concurrency Sessions at PDC
November 3
: PDC'09: Tutorial & Panel
October 26: Hoare on Testing
October 23
: Deprecating export Considered for ISO C++0x

Updated 2006.10.20

This page contains the complete current list of all known errata and updates for Herb Sutter's book Exceptional C++ (English edition).

This errata list is maintained by the author.

The individual errata entries are listed in page number order. For each one, I have included the page number as of the last printing not incorporating the suggestion (including "xref" cross-references to related entries for other pages), the severity (summarized below), the person who first reported the erratum and when, the earliest English printing incorporating the correction, and a description of the erratum and its correction.

Errata Categories

CategoryDescription
FmtFormat: Change to page layout or text formatting only.
TypTypo: Correction of simple typographical errors, cut-and-paste errors, and dyslexic mistakes.
EnhEnhancement: Addition of new or clarifying material.
CorCorrection: Change made to correct a substantive error that could mislead a reader; does not include typos and occasional dyslexia.

Errata (in page number order)

PageTypeReportedPrintingDescription

viii

Typ

2002.10.15
Ross Adamson

7

After inserting material on page 158, the index was updated but the Table of Contents entries weren't. In the Table of Contents, from the subhead "Traps, Pitfalls, and Anti-Idioms" onward, nudge the page numbers to point to the correct pages.

xii

Enh

2000.04.14
Michel Michaud

2001.10.10 hps

4

This book includes many guidelines, and in them I use the terms "always," "prefer," "consider," "avoid," and "never" with specific meanings. Those meanings were clearly explained in the coding standards appendix, but that appendix was held over to the next book and I never duplicated the explanations in the existing book. Also, URLs keep moving and the text shouldn't be allowed to get out of sync if we can help it. This change addresses both problems.

Immediately before the subhead "How We Got Here: GotW and PeerDirect," add the following new paragraphs:

This book includes many guidelines, in which the following words usually carry a specific meaning:

o   always = This is absolutely necessary. Never fail to do this.

o   prefer = This is usually the right way. Do it another way only when a situation specifically warrants it.

o   consider = This may or may not apply, but it's something to think about.

o   avoid = This is usually not the best way, and might even be dangerous. Look for alternatives, and do it this way only when a situation specifically warrants it.

o   never = This is extremely bad. Don't even think about it. Career limiting move.  

Finally, a word about URLs: On the Web, stuff moves. In particular, stuff I have no control over moves. That makes it a real pain to publish random Web URLs in a print book lest they become out of date before the book makes it to the printer's, never mind after it's been sitting on your desk for five years. When I reference other people's articles or Web sites in this book, I do it via a URL on my own Web site, www.gotw.ca, which I can control and which contains just a straight redirect to the real Web page. If you find that a link printed in this book no longer works, send me e-mail and tell me; I'll update that redirector to point to the new page's location (if I can find the page again) or to say that the page no longer exists (if I can't). Either way, this book's URLs will stay up to date despite the rigors of print media in an Internet world. Whew.

6

Cor

2001.03.06
Charles Cao

4

In the find() function, change:
return n > 0 ? s : 0;

To:
return n >= 0 ? s : 0;

9

Enh

2000.10.31
David X. Calloway

4

Change:
There are two ways to resolve this: Define insertion (
operator<<()) and extraction (operator>>()) for ci_strings yourself, or tack on ".c_str()" to use operator<<( const char* ):

To:
There are two ways to resolve this: Define
operator<<() and operator>>() for ci_strings yourself, or tack on ".c_str()" to use operator<<( const char* ) if your application's strings don't have embedded nulls:

15

Enh

2000.08.13
Howard Hinnant

4

In Item 5, the discussion of fixed_vector's templated assignment operator shows how to make it satisfy the strong exception-safety guarantee. Unfortunately, because this discussion comes before the discussion of the various exception safety guarantees it might be taken to imply that fixed_vector isn't exception-safe at all, which isn't true -- it does provide the basic guarantee. This is an artifact of the Items being reordered into sections: Item 5 (GotW #16) was originally written after Items 8 to 17 (GotW #8), and now the context needs to be pointed at better. Here's a quick 'fix.'

In the final paragraph, change:
Alas, it does. Did you notice that the templated assignment operator is not strongly exception-safe? Recall that it was defined as:

To:
Perhaps. Later in this book we'll distinguish between various exception safety guarantees (see Items 8 to 11, and page 38). Like the compiler-generated copy assignment operator, our templated assignment operator provides the basic guarantee, which can be perfectly fine. Just for a moment, though, let's explore what happens if we do want it to provide the strong guarantee, to make it strongly exception-safe. Recall that the templated assignment operator was defined as:

15

Cor

2000.08.12
Burkhard Kloss

4

The example code using std::copy() tries to copy a range of six objects into a target that's only large enough to hold four objects. We should only copy four objects.

Change:
copy( v.begin(), v.end(), w.begin() );

To:
copy( v.begin(), v.begin()+4, w.begin() );

16, 17

Cor

1999.12.28
Tim Butler

2

The strongly exception-safe version now requires an explicitly written copy constructor and copy assignment operator, implemented like the templated versions. Add these functions.

2000.02.21
Klaus Ahrens

2

Also, the non-default constructor is missing a memory allocation.

2000.08.13
Howard Hinnant

2001.08.14
Justin Gottschlich

4

Also, the original fix in printing #2 had another bug, now fixed in the code below.

Change:
template<typename O, size_t osize>
fixed_vector( const fixed_vector<O,osize>& other )
{
  copy( other.begin(),
        other.begin()+min(size,osize),
        begin() );
}

To:
template<typename O, size_t osize>
fixed_vector( const fixed_vector<O,osize>& other )
  : v_( new T[size] )
  { try {copy(other.begin(), other.begin()+min(size,osize), begin());}
    catch(...) { delete[] v_; throw; } }
fixed_vector( const fixed_vector<T,size>& other )
  : v_( new T[size] )
  { try {copy(other.begin(), other.end(), begin());}
    catch(...) { delete[] v_; throw; } }

And change:
template<typename O, size_t osize>
fixed_vector<T,size>&
operator=( const fixed_vector<O,osize>& other )
{
  fixed_vector<T,size> temp( other ); // does all the work
  Swap( temp );                       // this can't throw
  return *this;
}

To:
template<typename O, size_t osize>
fixed_vector<T,size>& operator=( const fixed_vector<O,osize>& other ) {
  fixed_vector<T,size> temp( other ); // does all the work
  Swap( temp ); return *this;         // this can't throw
}
fixed_vector<T,size>& operator=( const fixed_vector<T,size>& other ) {
  fixed_vector<T,size> temp( other ); // does all the work
  Swap( temp ); return *this;         // this can't throw
}

19

Cor

2001.11.15
Jarek Solowiej

6

Change the first code line from:
const T T::operator++(int)()

To:
const T T::operator++(int)

21

Enh

2000.10.01
Thomas Petillon

4

In the mid-page code example, the illustrated approach is of course only correct if the list is passed by reference. To make this clearer:

Change:
const string&
FindAddr( /* ... */ )

To:
const string&
FindAddr( /* pass emps and name by reference */ )

And change:
if( /* found */ )

To:
if( i->name == name )

22, 23

Typ

2001.12.03 hps

6

Bad page break, some text from the Item 7 question appears before the question heading itself.

Move the last 7 lines on page 22 (4 text and 3 code, starting with "How many pitfalls...") to immediately after the Item 7 question box on page 23 (ending with "...available in the standard library."). Thus the final brace at the end of what is now on page 22 would be the line immediately before the first code line "list<Employee>::const_iterator end...".

23

Enh

2001.11.19 Simon Liddington

6

At the end of the first solution paragraph (after "...from the original code.") insert the following additional sentence:

To:
For best effect to reduce temporaries, provide an
operator==() taking an Employee& and a name string&.

25

Enh

2001.10.10 hps

4

URL moved. Change the footnote's URL to http://www.gotw.ca/publications/xc++/sm_effective.htm

31

Cor

2000.08.13
Howard Hinnant

4

At the end of the paragraph numbered "2." change:
...must be unchanged.

To:
...must be destructible.

32, 33

Typ

2000.07.23
hps

4

Somehow the first presented version of Stack has a member function called Size() instead of Count(). For consistency with the later versions, not to mention Cargill's original article, it should be Count().

In one place on page 32 and four places on page 33, change:
Size

To:
Count

37

Enh

2000.01.15
Marc Briand

2

In the Common Mistake box, the wording should make it clearer that I'm criticizing code that cannot be made exception-safe because of the underlying design, not just code that happens to be incidentally exception-unsafe and only needs a local fix.

Cor

2000.08.24
Andrew Koenig

2000.08.24
Bill Wade

4

Also, as Andy Koenig pointed out to me, it is possible to write a copy assignment operator that is written in a such way that it must check for self-assignment and yet is strongly exception-safe (or better). Consider a copy assignment operator that is written in such a way that it must test for self-assignment to work properly, yet uses only nonthrowing operations such as builtin/pointer operations -- clearly it meets not just the strong guarantee, but even the nothrow guarantee! (Andy's example was of a class that implements an intrusive linked list, where assignment consists of removing the object from its current list and adding it to the other object's list; the obvious implementation requires a self-assignment check, yet uses only nonthrowing pointer operations.)

In the Guideline, change:
"Exception-unsafe" and "poor design" go hand in hand. If a piece of code cannot be made exception-safe, that almost always is a signal of its poor design. Example 1: A function with two different responsibilities is difficult to make exception-safe. Example 2: A copy assignment operator that has to check for self-assignment cannot be exception-safe.

To:
"Exception-unsafe" and "poor design" go hand in hand. If a piece of code isn't exception-safe, that's generally okay and can simply be fixed. But if a piece of code cannot be made exception-safe because of its underlying design, that almost always is a signal of its poor design. Example 1: A function with two different responsibilities is difficult to make exception-safe. Example 2: A copy assignment operator that is written in such a way that it must check for self-assignment is probably not strongly exception-safe either.

In the next paragraph, change:
... cannot be exception-safe.

To:
... is probably not strongly exception-safe.

37

Typ

2001.07.31
Garry Lancaster

4

In the final sentence of Item 10, change :
But a copy constructor that has to...

To:
But a copy assignment operator that has to...

38

Enh

2000.02.10
Dave Abrahams

4

URL moved, http://www.metabyte.com/~fbp/stl/eh_contract.html is now available via http://www.gotw.ca/publications/xc++/da_stlsafety.htm

39

Cor

2001.09.07
Manuel Menezes de Sequeira

4

In the fourth bullet paragraph, change:
...must guarantee that the target object is unchanged.

To:
...must guarantee that the target object is still a valid T.

42

Cor

2000.08.13
Howard Hinnant

4

The box implies that the helper functions construct() and destroy() are standard, when they aren't.

In the first paragraph, change:
...use three helper functions that are directly drawn (or derived in spirit) from the standard library:

To:
...use three helper functions, one of which (swap()) also appears in the standard library:

Delete the final paragraph:
To find out more about these standard functions, take a few minutes to examine how they're written in the standard library implementation you're using. It's a worthwhile and enlightening exercise.

42, 55, 56

Enh

2000.03.25
hps

4

This didn't make a difference in any example in the book, but it's a little odd: The two-parameter destroy(FwdIter,FwdIter) version is templatized to take any generic iterator, and yet it calls the one-parameter destroy(T*) by passing it one of the iterators... which requires that FwdIter must be a plain old pointer! This needlessly loses some of the generality of templatizing on FwdIter. A simple change lets FwdIter be pretty much any iterator type, not just a pointer: In destroy(FwdIter,FwdIter), change the call destroy( first ) to destroy( &*first ). This will work in all cases, unless T provides an operator&() that does not return a pointer which should occur rarely if ever.

On pages 42, 55, and 56, in three places change the two-parameter version of destroy() as above.

Change:
destroy( first );

To:
destroy( &*first );

See also GotW #68.

43

Typ

1999.12.23
Steve Vinoski

2

In paragraph 2, change:
StampImpl<T>

To:
StackImpl<T>

44

Enh

2001.09.07
Manuel Menezes de Sequeira

6

To make the choice of words more consistent between the Technique 1 and Technique 2 descriptions, under technique 1, paragraph 2, second-last line, change:
...any Stack constructor can even be called.

To:
...any Stack constructor body can be entered.

46

Enh

2001.09.07
Manuel Menezes de Sequeira

6

In paragraph 1, change:
...we won't enter the Stack constructor...

To:
...we won't enter the Stack constructor body.

And change:
(See Item 8 for...

To:
(See Item 8, and More Exceptional C++ Items 17 and 18, for...

46, 58

Typ

2000.05.24
Sam Lindley

4

In the Guideline, I say "initialization is resource acquisition" instead of "resource acquisition is initialization."

Change:
"initialization is resource acquisition"

To:
"resource acquisition is initialization"

48

Enh

2000.06.16
Stan Brown

4

To make it more obvious that other is passed by value and hence already a temporary object, change other to temp and add more explanation.

Change:
If you're one of those folks who like terse code, you can write the operator=() canonical form more compactly as:
  Stack& operator=(Stack other)
  {
    Swap( other );
    return *this;
  }

To:
If you're one of those folks who like terse code, you can write the operator=() canonical form more compactly using pass-by-value to create the temporary:
  Stack& operator=(Stack temp)
  {
    Swap( temp );
    return *this;
  }

49

Enh

2000.02.21
hps

4

In the paragraph following the bullets, it talks about 'if we allowed iterators,' but note that we do allow taking a reference into the container (via Top()) which is much the same thing.

Change:
If we were supporting iterators into this container, for instance, they would never be invalidated (by a possible internal grow operation) if the insertion is not completely successful.

To:
Any references returned from Top(), or iterators if we later chose to provide them, would never be invalidated (by a possible internal grow operation) if the insertion is not completely successful.

53

Cor

2001.09.07
Manuel Menezes de Sequeira

6

Under question 2, in the fourth bullet paragraph, change:
...must guarantee that the target object is unchanged.

To:
...must guarantee that the target object is still a valid T.

57, 58

Fmt

2000.07.24
hps

4

In the two Guidelines, the word "overloaded" should not be in code font.

64

Typ

1999.12.13
Jon Kalb

2

In paragraph 2, "addtion" should be "addition."

64

Enh

2001.09.07
Manuel Menezes de Sequeira

6

For greater clarity, in two places change:
are exception-safe (might throw but do not have side effects)

To:
are strongly exception-safe (might throw but do not have side effects)

70

Typ

2000.01.16
Douglas Gilbert

2

In the last line, "Item 19" should be "Item 39."

72

Cor

2000.01.16
Eric Nagler

2

In the second Guideline box, compound assignment operators need not be members.

2000.01.24
hps

2

Also, these rules should be revised based on Scott Meyers' article "How Non-Member Functions Improve Encapsulation" (C/C++ Users Journal, 18(2), February 2000) and Exceptional C++'s own arguments about nonmember functions in Items 31-34.

2000.08.24
hps

4

The initial fix was slightly wrong (a typo: it said "member" where it meant "nonmember"). I also forgot about the requirement that operators new, new[], delete, and delete[] be static members. What is shown below should now be correct.

Change:
-- Unary operators are members.
--
= () [] and -> must be members.
-- The assignment operators (+= --= /= *= and so forth) must be members.
-- All other binary operators are nonmembers.

To:
The standard requires that operators = () [] and -> must be members, and class-specific operators new, new[], delete, and delete[] must be static members. For all other functions:

if the function is operator>> or operator<< for stream I/O,
or if it needs type conversions on its leftmost argument,
or if it can be implemented using the class
's public interface alone,

make it a nonmember (and friend if needed in the first two cases)

if it needs to behave virtually,

add a virtual member function to provide the virtual behavior,
and implement it in terms of that

else
make it a member.

82. 90

Enh

2000.09.07
Thomas Petillon

4

For consistency, once on page 82 and twice on page 90, "aggregation" should be "containment."

83

Enh

2001.09.08
hps & various

4

Every so often someone reports "iff" as a typo, but it's no. In mathematical logic, it's a standard short form for "if and only if." To avoid confusion, however, I'll spell it out.

In the code comment, change :
iff

To:
if and only if

84, 86

Enh

2000.08.30
Thomas Petillon

4

(For more details see the comment for pages 153-154.)

In most of the book I demonstrate the Pimpl idiom using struct for both the declaration and the definition of the Pimpl class. On pages 84 and 86 I don't, so for consistency, once each in the first line of page 84 and in the middle of page 86:

Change:
class GenericTableAlgorithmImpl* pimpl_; // MYOB

To:
struct GenericTableAlgorithmImpl* pimpl_; // MYOB

84, 87

Typ

2000.01.12
Steve Vinoski

2

In the example code comment "override Filter() and ProcessRow() do implement a specific operation," "do" should be "to."

85, 105, 110

Cor

2001.09.07
Manuel Menezes de Sequeira

6

In three Guidelines, change:
struct XxxxImpl* pimpl_;

To:
struct XxxxImpl; XxxxImpl* pimpl_; 

And change:
struct MapImpl* pimpl_;

To:
struct MapImpl; MapImpl* pimpl_;

92, 95

Enh

2000.02.10
M. Thomas Groszko

4

URL moved, www.oma.com is now http://www.gotw.ca/publications/xc++/om.htm

100

Typ

2000.09.07
Thomas Petillon

4

The first line "using namespace std;" is redundant and shouldn't be there.

Remove the first line:
using namespace std;

103

Typ

1999.12.27
Kjell Swedin

2

In the last line, "Lokos96" should be "Lakos96."

104, 105, 107, 108, 109, 113, 114

Cor

2001.08.06
Alexander Erdei

4

Once on each page, change:
struct XImpl* pimpl_;

To:
struct XImpl;
XImpl* pimpl_;

106

Enh

2000.09.07
Thomas Petillon

4

The sense should be understood, but to be consistent with page 102, in the second paragraph of Item 28:

Change:
...
so that existing code that uses X is unaffected.

To:
...so that existing code that uses X is unaffected beyond requiring a simple recompilation.

107

Enh

2000.02.10
M. Thomas Groszko

4

URL moved, www.oma.com is now http://www.gotw.ca/publications/xc++/om.htm

107

Typ

2000.01.12
Steve Vinoski

2

In the first Solution paragraph, I refer to a future Item that is actually earlier in the book.

Change:
I'll save the whole lecture for a later Item, but my bottom line is simply that...

To:
See Item 24 for the whole exhausting lecture; the bottom line is simply that...

108

Cor

2000.04.30
Brian Danilko

4

A forward declaration is still needed for class B, because B is still mentioned in some function declarations.

In the first paragraph, delete the text:
and in order to get rid of the b.h header entirely,

In the code, before the line "class C;" insert a new line:
class B;

110

Typ

2000.09.01
Tetsurch Asahata

4

In the second paragraph, "at at time" should be "at a time."

110

Typ

2000.10.06
hps

4

In Option 1, change:
(rather than #include the class's actual declaration,

To:
(rather than #include the class's actual definition,

110

Enh

2000.12.05
John McGuinness

4

In Option 2, change:
Option 2 (Score: 10 / 10): Put all private members into XImpl.

To:
Option 2 (Score: 10 / 10): Put all nonvirtual private members into XImpl.

Change the following paragraph:
There are some caveats, the first of which is the reason for my "almost" above.

To:
There are some caveats.

In the following bullet, change the paragraph:
Making a virtual function private is usually not a good idea, anyway. The point of a virtual function is to allow a derived class to redefine it, and a common redefinition technique is to call the base class's version (not possible, if it's private) for most of the functionality.

To:
Virtual functions should normally be private, except that they have to be protected if a derived class's  version needs to call the base class's version (for example, for a virtual DoWrite() persistence function).

110

Cor

2001.09.07
Manuel Menezes de Sequeira

6

Change:
This is a good start, because now we can forward-declare any class that appears only as a data member (rather than
#include the class's actual declaration, which would make the client code depend on that too). Still, we can usually do better.

To:
This is a good start, because it hides any class that appeared only as a data member. Still, we can usually do better.

113

Typ

2000.03.21
Klaus Ahrens

4

In the paragraph following the output 1 and 8, "X2" should be "X."

Change:
...inside each X2 object...

To:
...inside each X object...

115, 116

Enh

2001.09.07
Manuel Menezes de Sequeira

6

The numbering in this sidebar could be confusing.

On page 116, in the last code fragment, change:
(#1)

To:
(A)

And change:
(#2)

To:
(B)

On the first line of page 117, change:
#1 or #2

To:
A or B

118

Typ

2000.09.07
Thomas Petillon

4

Footnote 10 should not exist. Delete it.

124

Typ

2000.01.12
Steve Vinoski

2

In the third-to-last line, "an" should be "and."

127

Enh

2000.09.07
hps

4

At the top of the page, I present two options. Technically there's one more option: A using declaration for std::operator<<().

Change:
...have to write either "std::operator<<( std::cout, hello );" which is exceedingly ugly, or "using namespace std;" which dumps all the names in std into the current namespace and thus eliminates much of the advantage of having namespaces in the first place.

To:
...have to write either "std::operator<<( std::cout, hello );" which is exceedingly ugly, or "using std::operator<<;" which is annoying and quickly becomes tedious if there are many operators, or "using namespace std;" which dumps all the names in std into the current namespace and thus eliminates much of the advantage of having namespaces in the first place.

127

Typ

2000.08.12
hps

4

In the footnote, "article" should be "Item."

Change:
...later in this article.

To:
...later in this Item.

131

Cor

2001.02.04
Simon Ditrich

4

In Example 5(b), change:
virtual ostream& print( ostream& );

To:
virtual ostream& print( ostream& ) const;

And change:
ostream& X::print( ostream& o )

To:
ostream& X::print( ostream& o ) const

132

Typ

2000.01.12
Steve Vinoski

2

In the paragraph starting "Finally,"  change:
...is a member function of a:

To:
...is a member function of A:

133

Typ

2000.10.01
Thomas Petillon

4

At the bottom of the page, change:
// Example 1: Will this compile?

To:
// Example 2: Will this compile?

135

Enh

2001.09.07
Manuel Menezes de Sequeira

6

Change:
...performing overload resolution and applying access rules.

To:
...performing overload resolution and then applying access rules.

140

Enh

2001.09.07
Manuel Menezes de Sequeira

6

In the Guideline, change:
If you put a class into a namespace, be sure to put all helper functions and operators into the same namespace, too.

To:
If you write a class in some namespace N, be sure to put all helper functions and operators into N, too.

141

Enh

1999.12.08
hps

2

Needs to stress more strongly that "heap" and "free store" are commonly used terms, not words from the standard.

At the end of the final sentence, add:
; in particular, "heap" and "free store" are common and convenient shorthands for distinguishing between two kinds of dynamically allocated memory

144, 148

Enh

2002.02.06
Gerhard Geldenbott

6

The line of code "B b;" is redundant as the object b is never used.

On page 144,  question 3, code line 1, remove the line:
B b;

On page 148,  quoted question 3, code line 1, remove the line:
B b;

145

Typ

2001.07.31
Garry Lancaster

4

Change the line:
static void Deallocate( void* p, int i )

To:
static void Deallocate( void* p, int i = 0 )

149

Typ

1999.12.08
hps

2

In the code example, change:
new (shared) T; // if T::T() throws, memory is leaked

To:
new (shared) Y; // if Y::Y() throws, memory is leaked

151, 157, 158

Cor

2000.01.11
Douglas Gilbert

2

At the top of page 151, toward the end of the code example, add "/*...*/" after "private:".

At the bottom of page 157, add "/*...*/" after "private:".

At the top of page 158, add the following new paragraph:
Possible issue: One of the /*...*/ areas (whether public, protected, or private) had better include at least declarations for copy construction and copy assignment.

153, 154

Enh

2000.08.23
Thomas Petillon

4

It's perfectly legal and standards-conforming to forward-declare a class as a struct and vice versa. In most of the book I've tended to avoid doing that, though. Why? Only because some compilers are buggy and still don't get this right -- e.g., by name-mangling a class and a struct differently, which will cause the linker to fail to match them up. Such compiler bugs really are bugs and are wrong, but they're common enough that we might as well avoid the issue by not relying on this standard feature. Sigh.

Specifically, in most of the book I demonstrate the Pimpl idiom using struct for both the declaration and the definition of the Pimpl class. On pages 153 and 154 I don't, so for consistency, once each in Example 4(a) and 4(b):

Change:
class C::CImpl { /* ... */ };

To:
struct C::CImpl { /* ... */ };

154

Enh

1999.12.08
hps

2

In the first paragraph following Example 4(b), after the first sentence add:
Better still, it means C::C() has to do less work to detect and recover from constructor failures because pimpl_ is always automatically cleaned up.

158

Enh

1999.12.08
hps

4

ADD NEW MATERIAL: Before "The const auto_ptr Idiom" add the new section "auto_ptr and Exception Safety."

160

Typ

2000.05.14
hps

4

In the second guideline, the word "to" is missing.

Change:
It's all right use a ...

To:
It's all right to use a ...

160

Cor

2000.08.24
Andrew Koenig

4

(See the discussion for the corresponding erratum for page 37.)

In the second paragraph, change:
If T::operator=() is exception-safe, it doesn't need to test for self-assignment. Period. Because we should always write exception-safe code, we should never perform the self-assignment test, right?

To:
If T::operator=() is written using the create-a-temporary-and-swap idiom (see page 47), it will be both strongly exception-safe and not have to test for self-assignment. Period. Because we should normally prefer to write copy assignment this way, we shouldn't need to perform the self-assignment test, right?

In the following Guideline, change:
... an exception-safe copy assignment operator is automatically safe for self-assignment.

To:
... a copy assignment operator that uses the create-a-temporary-and-swap idiom is automatically both strongly exception-safe and safe for self-assignment. `

161

Enh

2000.06.22
hps

2001.09.07
Manuel Menezes de Sequeira

4

In the footnote, at the end of the final paragraph ("Yikes..."), append:
Similarly, the following code is also not valid C++, in that it's syntactically legal (a conforming compiler must accept it) but has undefined behavior (a conforming compiler may legitimately emit code that will reformat your hard drive). If the code were valid, it would also make the test meaningful:
  T t = t; // invalid, but it would make the test meaningful

164

Typ

2000.09.15
Thomas Petillon

2001.07.31
Garry Lancaster

4

In the last paragraph, in two places change:
t.f()

To:
t.DestroyAndReconstruct()

168

Typ

2000.05.24
Sam Lindley

4

In the last line, I say "initialization is resource acquisition" instead of "resource acquisition is initialization."

Change:
"initialization is resource acquisition"

To:
"resource acquisition is initialization"

169

Cor

2000.08.24
Andrew Koenig

2000.08.24
Bill Wade

4

(See the discussion for the corresponding erratum for page 37.)

At the bottom of the page, change:
Any copy assignment that must check for self-assignment is not exception-safe.

To:
Any copy assignment that is written in such a way that it must check for self-assignment is probably not strongly exception-safe.

172

Enh

2000.08.12
hps

4

C++ Report no longer exists, so remove it.

174

Cor

2000.12.12
Mark Handy

4

After the code example "T t(u);", change:
This is direct initialization. The variable t is initialized directly from the value of u by calling T::T(u).

To:
Assuming u is not the name of a type, this is direct initialization. The variable t is initialized directly from the value of u by calling T::T(u). (If u is a type name, this is a declaration even if there is also a variable named u in scope; see above.)

176

Typ

2000.01.18
Douglas Gilbert

2

In the code example at the bottom of the page, in the comment "not the same as f(int&)," "f(int&)" should be "g(int&)."

176

Enh

2000.08.21
Robert Dick

4

In the Guideline, change:
Avoid declaring const pass-by-value function parameters.

To:
Avoid const pass-by-value parameters in function declarations. Still make the parameter const in the same function's definition if it won't be modified.

177

Cor

2001.07.31
Garry Lancaster

4

In the first non-numbered paragraph, change:
As we will see later, it makes sense for GetPoint() to return a const value or a reference to const for another reason:

To:
As we will see later, it makes sense for GetPoint() to be a const member function for another reason: 

179

Cor

2001.07.31
Garry Lancaster

4

In the first paragraph, remove the text:
returning either a const value or a reference to const

179

Enh

2001.07.31
Garry Lancaster

4

In the second text paragraph, change:
Bonus: The result...

To:
Bonus: Using the result...

179

Typ

1999.11.26
hps

2

Vestigial plural.

Change:
(If, in looking for the "bonus" part, you said something about these two functions being uncompilable--sorry, they're quite legal C++. You were probably thinking of putting the const to the left of the & or *, which would have made the function body illegal.)

To:
(If, in looking for the "bonus" part, you said something about this function being uncompilable--sorry, it's quite legal C++. You were probably thinking of putting the const to the left of the *, which would have made the function body illegal.)

180, 181, 182

Fmt

1999.11.26
hps

2

Move page 182 to page 180 (so that 180/181 become 181/182) to put the box closer to the text it accompanies.

181, 182, 183

Fmt

1999.11.26
hps

4

Restore the originally intended vertical whitespace to the Item 44 question code to make it more readable.

184

Enh

2001.07.31
Garry Lancaster

4

In the first  paragraph, change:
...the results are undefined.

To:
...the results of using the pointer are undefined.

185

Cor

1999.12.28
Chris Uzdavinis

2

The commentary for pa3 code line doesn't take into account possible friendship.

Change:
Error: Because
b1 IS-NOT-AN A (because B is not publicly derived from A; its derivation is private), this is illegal.

To:
Probable error: Because
b1 IS-NOT-AN A (because B is not publicly derived from A; its derivation is private), this is illegal unless g() is a friend of B.

188

Typ

2000.08.13
Philip Brabbin

4

In Option 2, the #define directive is backwards.

Change:
#define int   bool

To:
#define bool  int

194

Cor

2001.02.19
Tom Bjorkholm

4

In the last line, change:
int fileIdCounter = 100; // start count at 100

To:
int fileIdCounter = InitFileId(); // starts count at 100

196

Typ

2000.01.01
George Reilly

2

At the bottom of the page, the Resize() function contains a spurious memset() call that is incorrect and was not in the original question.

Delete:
memset( buffer_, ' ', newSize );

197

Typ

2000.10.01
Thomas Petillon

4

In the expansion of the return statement, change:
", y = " ) ,

To:
", used = " ) ,

201

Enh

2001.02.20
hps

4

The GotW website has moved, so change:
www.PeerDirect.com/resources

To:
www.gotw.ca

201

Enh

2000.08.12
hps

4

C++ Report no longer exists, so remove it.

203

Typ

2000.07.17
hps

4

Nathan's last name is Myers, not Meyers. In the Meyers97 reference, change "Meyers" to "Myers" in both places.

204

Enh

2001.10.10 hps

4

Change the Meyers99 reference's URL to http://www.gotw.ca/publications/xc++/sm_effective.htm

Index

Enh

2000.07.01
Scott Meyers

4

REPLACE INDEX: A more thorough index for the first three printings is provided here. It appears in the book from the fourth printing onward.

 

Copyright © 2009 Herb Sutter