|
Last Updated March 17, 2008 by Scott Meyers Note: This document applies to only the third edition of Effective C++. Errata for earlier editions of the book are available as follows: What follows are my notes on what I've changed in the third edition of Effective C++ since its original publication (i.e., since its first printing) and what I believe may need to be changed in future printings. Most of the changes (or prospective changes) are cosmetic and don't affect the technical content of the book. To distinguish those modifications that do affect technical material, I precede those entries with an exclamation mark ("!") and display them in red. Each entry includes the following information:
I am always interested in bug reports and suggestions for improvements to Effective C++. To submit comments, send email to ec++@aristeia.com . To be assured of always having the most accurate version of Effective C++ at your fingertips, I encourage you to buy a copy of each printing :-). The following changes were made for the second printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's the first printing.
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
6/ 1/05 rxy 30 References to the variable "theFileSystem" should 7/ 4/05
be replaced with the variable "tfs" in the last
two sentences.
6/ 2/05 rxy 52 In 4th line of 2nd para, "that going" ==> "than 7/ 4/05
going".
6/ 2/05 rxy 79 In the third code example, "Date d(2, 20, 1995)" 7/ 4/05
is incorrect, because that's a valid date.
I changed the example to "3, 40".
6/ 2/05 rxy 83 2nd line of 1st bullet. "Your should" ==> "you 7/ 4/05
should".
5/ 4/05 jxr 122 In code at top of page, SpecialWindow::blink 7/ 4/05
has an unnecessary semicolon at the end of its
definition.
6/ 6/05 sdm 231 There's unnecessary extra vertical space after 7/ 4/05
the last statement in the 2nd impl of doAdvance.
The following changes were made for the third printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first two printings.
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
8/19/05 axf 4 In last para, "objects of user-defined types" 10/10/05
==> "objects generated from structs and classes".
7/ 5/05 bxm 20 In several code examples, the quote character is 10/10/05
21 "`" instead of "'".
7/ 5/05 bxm 31 I added a comment at the end of the next-to-last 10/01/05
32 para on pg. 31: "Actually, it's only part of
a Singleton implementation. An essential part of
Singleton I ignore in this Item is preventing the
creation of multiple objects of a particular type."
7/ 5/05 bxm 81 In 2nd-to-last sentence, "delete" should be in 10/10/05
code font.
7/11/05 gxk 82 In 2nd-to-last para, "pInv" ==> "retVal." 10/10/05
7/26/05 bxm 86 Explicitly declare Student destructor virtual. 10/10/05
(It's already implicitly virtual.)
9/26/05 mxs 93 In last para, I added this footnote: "The 10/10/05
destructors will be called once at program
shutdown."
8/24/05 jds 105 Extra space before the period in the last line 10/10/05
before the "Things to Remember" heading.
7/26/05 bxm 115 Remove "std::" qualification in definition of 10/10/05
the variable encrypted for consistency with
page 114.
7/26/05 bxm 124 In 2nd-to-last line, "ulhc and lrhc are declared 10/10/05
125 private" ==> "ulhc and lrhc are supposed to
be private to their Rectangle".
7/ 8/05 ixl 125 In 2nd-to-last para, "upperRight" ==> 10/10/05
"lowerRight".
7/11/05 gwj 126 "It" at beginning of 2nd sentence of "Things to 10/10/05
Remember" bullet is ambiguous. Reword.
8/18/05 clt 160 The example at the bottom of the page is odd, 10/10/05
because Derived::mf1 calls Base::mf1, which is
pure virtual. I added an xref to Item 34, which
explains that pure virtuals may be defined.
7/26/05 bxm 162 In 3rd para, error should be private it if it's 10/10/05
only called by member functions. Hence "is
called by member functions if they need to report
an error" ==> "is called when an error needs
to be reported".
! 10/ 5/05 jsl 174 In 2nd prose paragraph, the definition of 10/10/05
compatibility is incorrect. A callable entity
is compatible if a const GameCharacter& can be
passed to it, i.e., if its parameter type is
either const GameCharacter& or something that
a const GameCharacter& can be implicitly
converted into.
! 10/ 5/05 jsl 175 The first sentence of the last paragraph is 10/10/05
inaccurate. It's not the "_1" that specifies
that currentLevel is to be used as the GameLevel
object when calling GameLevel::health, it's the
location of currentLevel in the parameter list
to tr1::bind. The "_1" itself, in conjunction
with its position in tr1::bind's parameter list,
specifies that the argument passed to the
function object generated by tr1::bind should
then be passed as the parameter to
GameLevel::health. I reworded to avoid
mentioning _1 at all.
7/25/05 tdh 207 In 3rd para, "vary" ==> "varies". 10/10/05
10/12/05 jsl 231 In first para, "create two versions" ==> 10/10/05
"create multiple versions".
8/ 1/05 bxm 242 As return type of operator new or as an unnamed 10/10/05
244 parameter, "void *" ==> "void*". This it to
245 follow consistent conventions in the book.
252
254
255
258
10/ 5/05 sdm 263 The target year for C++0x has been set at 2009, 10/10/05
264 with all substantive work finished by the end
of 2007. (It takes a year or so after all work
is done to make the new standard official.)
! 10/ 5/05 sdm 266 In 1st para, "anything convertible to an int" ==> 10/10/05
"anything an int can be converted into".
9/11/05 pxh 269 In 1st bullet at top of page, "C99"==> "C89". 10/10/05
The following changes were made for the fourth printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first three printings.
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
1/26/06 ser 32 In
The following changes were made for the fifth printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first four printings.
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
8/2/06 bxs 18 One way to remember what const refers to when 11/21/06
pointers are involved is to read the declarations
right to left:
char *p // ptr to char
const char *p // ptr to char that is
// const
char const *p // ptr to constant char
char *const p // constant ptr to char
const char * const p // constant ptr to char
// that is const
char const * const p // constant ptr to
// constant char
I added a footnote mentioning this idea.
7/28/06 lfr 46 In middle code example, red block is terminated 11/21/06
with a black brace. The brace should be red.
! 7/17/06 nxd 108 Text after top code example says that STL 11/21/06
containers specialize std::swap. This is
incorrect; they overload std::swap as
described on page 109. I changed
"specializations" to "versions" to dance around
this issue until it's discussed on the next
page.
8/26/06 lfr 177 Missing "of" in last sentence of 2nd para. 11/21/06
! 10/31/05 clt 214 The "this->" in SquareMatrix::invert is 11/21/06
10/ 4/06 hgv 215 unnecessary, because the using declaration for
281 SquareMatrixBase::invert allows the name "invert"
291 to be looked up in the base class (as noted on
295 page 211). I updated the comment for the
using declaration to indicate that both Items 33
and 43 are being addressed, and I modified the
text of the following paragraph. These changes
modified the page break with page 215 and also
eliminated some index entries.
1/18/06 vxp 214 To prevent the code bloat discussed in this 11/21/06
Item, it's important that
SquareMatrixBase::invert not be declared inline.
7/ 7/06 yxf 286 The entries
LoggingMsgSender::sendClear 208, 210
LogginMsgSender::sendClear 210, 211
should be merged as
LoggingMsgSender::sendClear 208, 210, 211
The following changes were made for the sixth printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first five printings.
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
5/08/07 sdm xvii In first para, "about five years" ==> "about 5/08/07
three years" and "two decades" ==> "nearly two
decades".
6/29/06 axd 22 Add a remark that the definition of "const" that 5/08/07
programmers should follow for const member
functions is logical constness, not bitwise
constness. (The information is already bullet 2
on page 26, but putting it here makes the
point sooner.)
12/31/06 ahh 26 In 2nd summary bullet, "conceptual constness" 5/08/07
==> "logical constness".
10/14/05 ejx 30 Reworded code comments to make clearer that the 5/08/07
code on this page would be in a header file and
that tfs' definition would be in a separate .cpp
file somewhere.
2/25/07 mxr 36 In first code example, "<class T>" ==> 5/08/07
"<typename T>" (for consistency with pg. 35).
12/31/06 ahh 37 In second para, "If you want to support 5/08/07
assignment" ==> "If you want to support copy
assignment".
6/27/06 bp 71 To Font class at top of page, add a "..." to the 5/08/07
code and a comment that, per Item 14, the class
must handle copying somehow.
3/27/07 dxs 209 Last line of last code comment should read 5/08/07
"// sendClear is omitted".
12/31/06 ahh 216 In 2nd prose para, "simple inline calls to base 5/08/07
class versions" ==> "simple inline calls to
(non-inline) base class versions."
2/ 8/06 awo 230 In first code example, "IterT" ==> "T" (because 5/08/07
the pointer itself is the iterator, T is just
what it points to).
The following changes were made for the seventh printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first six printings.
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
9/15/07 dmr 7 Wrong type of quotes in "Darla". 1/28/08
3/18/07 mxr 55 Final sentence of top para is not technically 1/28/08
correct, because C++ implementations are allowed
to change the value of a deleted pointer,
although I don't know any that do.
5/10/07 sdm 107 In second code fragment, move "this won't compile" 1/28/08
comment to the line trying to access the
pImpl pointers.
9/15/07 dmr 118 Should mention that the two cast forms shown at 1/28/08
the top of the page yield identical behavior,
e.g., both create temporary Widget objects.
9/15/07 dmr 125 In 1st para, comma preceding the parenthetical 1/28/08
comment should be a period.
9/15/07 dmr 145 In comment at top of page, "exactly the same 1/28/08
member functions" ==> "exactly the same public
member functions".
! 7/28/07 mxh 158 In first line on page, "containing Base" ==> 1/28/08
"containing Derived".
! 12/22/07 lfr 193 In 1st para, "checkOut" is ambiguous during name 1/28/08
lookup, not overload resolution; and the two
"checkOut" functions are not equally good
matches, because one is const and one is not.
7/17/07 mxr 197 Class definition of PersonInfo should match that 1/28/08
shown on page 195.
10/ 3/07 bxj 239 3rd para should make clear that the new-handler 1/28/08
is a global resource and thus subject to the
thread-safety issues that apply to all such
resources.
The following changes have been proposed but have not yet been published:
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- -------------------------------------------------- -----
11/ 4/07 nxd 18-19 The text implies that all by-value returns should
be const, but cases where non-const by-value
returns are good design are not difficult to find,
e.g., return types of std::vector<T> where callers
will use swap with an empty vector to "grab" the
return value contents without copying them.
Reword.
What follows are interesting comments about the material in Effective C++, Third Edition, but I don't expect to be able to modify the book to take these comments into account until (if ever) I write a fourth edition.
DATE
REPORTED WHO PAGES WHAT
-------- --- ------- ----------------------------------------------------------
9/26/06 jxm 2 The book says it limits itself to standard C++, but the
book also shows use of non-standard libraries such as TR1
and Boost. (This is true, but the book uses no
non-standard language features, only portable libraries
presenting standard-conforming interfaces.)
5/ 6/05 exa Item 2 "In one of my recent projects, I have to use 2 third party
libraries and both of them had a symbol define with the
same name, like in one library
#define SOMETHING 1
and in another
#define SOMETHING 2
now, while compiling, the second one overrights the first
one. I tried with the namespace, but still no luck, later
on, I've to do the manual stuff. At that time, I really
appreciated your Item about avoiding #define.
I didn't find this specific issue in your item (and not
anywhere else also), so I'm just forwarding it to you."
11/ 2/07 nxd 18-19 Declaring by-value function return values const will
prevent their being bound to rvalue references in C++0x.
Because rvalue references are designed to help improve
the efficiency of C++ code, it's important to take
into account the interaction of const return values
and the initialization of rvalue references when
specifying function signatures.
9/12/05 pxh 24 Unfortunately, even const_cast can't be used to cast a
const_iterator to an iterator. For details, consult Item
27 of Effective STL (available online as part of
my June 2001 CUJ article, where it's known as Guideline 2)
as well as the newsgroup discussion of the matter.
11/21/06 pxw 32 pxw reports that some compilers (notably Sun's) won't
inline functions containing static data. Compilers
don't have to inline anything, but if inlining is
important to you, be on the lookout for this issue.
7/25/05 tdh 33-34 Using functions to return references to local static
objects is a good way to avoid referring to uninitialized
objects, but local static objects are automatically
destroyed (in the reverse order in which they were
constructed) at program shutdown, and this means that it
is possible for the destructor of one local static object
to refer to another local static object that has already
been destroyed. [For a good discussion of this problem
and two possible ways to deal with it, consult sections
6.5-6.8 of Andrei Alexandrescu's Modern C++ Design.
--Scott]
7/28/06 lfr Item 6 Inheriting from a base class like Uncopyable or
boost::noncopyable can be more convenient than manually
declaring the copying functions private, because the base
class does not disable the automatic generation of a
default constructor, but manually declaring a copy
constructor does (per Item 5).
11/26/06 nxd Item 6 If a class C declares the copying functions private and
defines a function f that performs copying, but f is never
called, the code will compile and link. (If f is called,
the code will not compile.) To prevent this (unlikely)
problem, nxd suggests:
- Have C's operator= return an incomplete type.
- Declare C's copy constructor explicit (i.e., prefix it
with the "explicit" keyword).
9/ 8/05 wxv 47 wxv notes that if a client calls DBConn::close, and that
2/ 3/07 sxf call throws an exception, the database did not close
successfully, but in some libraries, calling close on it
again (in the DBConn destructor) would be harmful. It
might thus be better to use an enum instead of a bool to
keep track of the state of the database, e.g.,
enum DBStatus { Open, Closed, AttemptToCloseThrew };
sxf argues that this approach leads to the destructor
trying to close the connection again if the call to close
throws, and that puts us back in our original position.
A better design might be to change the enum to
enum DBStatus { Open, CloseAttempted };
and not try to invoke close if it's already been called.
6/27/06 pxg Item 15 A way to minimize the need to access raw resources is
to wrap legacy APIs with ones that know about resource
managers. For example, daysHeld (at the bottom of
page 69) and releasefont (at the bottom of page 70) could
be augmented with these functions, which clients could
then call with resource-managing objects:
int daysHeld(const std::auto_ptr<Investment> p)
{ return daysHeld(p.get()); }
void releaseFont(Font f) { f.get(); }
6/12/05 sdm Item 17 The reasoning in this Item applies to more than just
dynamically allocated memory. It should be revised to
apply to resource acquisition in general.
6/19/05 mxm Item 23 mxm notes that this Item doesn't discuss the ramifications
of the different calling syntaxes for member and non-member
functions. However, I do discuss this issue in the article-
length treatment of this topic. (Scan for "Syntax Issues.")
8/26/07 mxd Item 23 "A C++ pattern that I have often seen is that there'd be a
big hairy class with a ton of methods that all work
together to get some giant job done. If a certain style
is followed, the logic of that job can be very hard to
follow. That style is having MethodA do a ton of work and
then call MethodB (and possibly MethodC, MethodD, ...,
MethodZ) with few if any arguments to the call. The
methods are all of the same class, so basically they are
handing off "arguments" to one another by what amounts to
file-global variables: the member variables of the class.
In my mind the self-documenting quality of a piece of code
is carried almost entirely on the shoulders of the names
of functions and arguments passed to them. If you throw
away the arguments you lose half the visual meaning behind
every method call, and it makes the code terribly hard to
read. In other words, whenever you see MethodA call
MethodB in the same class, all you know vis-à-vis the
data flow is that it involves (a) the arguments passed
(if any) and (b) a potentially arbitrary subset of the
member variables. It’s just plain global-variables
lite. And it is avoided completely if you stick to
non-member, non-friend functions as much as possible."
7/19/06 nxd 110-111 Putting "using std::swap;" in a function calling swap is
not sufficient to ensure that the proper swap will always be
called. For details, consult this Usenet thread
devoted to this topic. The C++ Standardization
committee has addressed the broader issue present here via
a defect report on the matter.
6/ 7/07 clt 115-116 If the operand to the assignment in loop Approach A is
not of a type taken by a Widget assignment operator, a
temporary may be introduced. If this happens, each
call to Widget's operator= will incur the cost of a
temporary construction and destruction.
6/29/05 dxe Item 27 One way to reduce the need for downcasts is to take
advantage of C++'s support for covariant return types in
member functions like
Who's who:jxr = Jason Ross rxy = Robert Yokota exa = Ejaz Anwer mxm = Marc Mutz dxe = Dick Eimers ixl = Idan Lupinsky bxm = Bernhard Merkle gwj = G. Wade Johnson gxk = Gerhard Kreuzer tdh = T. David Hudson clt = Clovis Tondo axf = Attila Feher bgn = Brian Neal jds = J. Daniel Smith pxh = Phillip Hellewell wxv = Walter Vannini mxs = Marcin Sochacki jsl = Joshua Lehrer ejx = Ed Ji Xihuang jxc = Jiongxiong Chen mxd = Michael Drumheller axh = Andrew Henrick vxs = Vincent Stojanov kxk = Ken Kobayashi ser = Eldar Ronen vxp = Vasily Poshehonov awo = Tony Oliver clm = Cameron Mac Minn jeh = John Hershberger txs = Thomas Schell axd = Alex Dumov bp = Balog Pal pxg = Paul Grenyer yxf = Yukitoshi Fujimura nxd = Niels Dekker lfr = Fraser Ross bxs = Balbir Singh hgv = Harsh Gaurav Vangani jxm = Jürgen Messerer mxr = Mike Rizzi ahh = Alex Howlett sxf = Solomon Foster dxs = David Solomon hxs = Hendrik Schober pxw = Peter Weinert mxh = Miaohua bxj = Brian Johnson dmr = Martin Rottinger sxo = Sergei Otarov From here you may wish to visit the Amazon Page for Effective C++, Third Edition. |
||||||
|
||||||