Scott Meyers
Modification History and Errata List for Effective C++, Third Edition
Last Updated 22 June 2021
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:
- Date Reported: The date the problem was brought to my attention.
- Who: The initials of the person reporting the problem. The initials "sdm" refer to me. The mapping from other initials to full names is at the bottom of this document.
- Pages: The pages of the book (or the Item number) affected.
- What: A description of the problem and the solution.
- Date Fixed: The date on which I fixed the problem. If no date is shown, it means I haven't gotten around to fixing the bug or I'm still mulling over whether I want to fix it. Sometimes I change my mind on bug reports, so prospective bugs often spend quite a while in the "not yet fixed" state. When Addison-Wesley notifies me that a new printing is about to take place, I go through the bugs and fix all those I've decided must be fixed. It's thus not uncommon for all the bugs fixed for a particular printing to have the same fix date.
The easiest way to use this list is to find out which of the book's printings you have (it's listed on the copyright page near the bottom), then go to the appropriate section of the list and read from that point forward. For example, if you have a copy of the third printing, the changes made to the first and second printings won't apply to you, because the changes will already be in place in your copy of the book.
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 IntempDir
, initialization oftd
is missing 6/17/06 "( params )
". 1/25/06 bxm 47 Code for~DBConn
is missing a close } for the 6/17/06 openingif
statement, and the block controlled by theif
needs to be indented. 2/17/06 clm 62 In para after 2nd code fragment, "continue or 6/17/06 goto statement" ==> "break or goto statement". 3/16/06 jeh 62 "Regardless of how the delete were skipped," ==> 6/17/06 "...were to be skipped," 3/27/06 axd 105 Reword bullet at bottom of page, because non- 6/17/06 member functions don't have a this pointer. 12/23/05 vxs 158 In 3rd para, "Derived's overloading of mf3" ==> 6/17/06 "Derived's declaration of mf3". 1/ 4/06 vxs 183 In last two paras, "overridden/overriding" ==> 6/17/06 "redefined/redefining". 3/16/06 jeh 201 "con-stnesses" ==> "const-nesses". 6/17/06 12/29/05 sdm 210 In 3rd para, "Object-oriented" ==> 6/17/06 "Object-Oriented". 11/17/05 axh 229 Both nested iterator classes should end with a 6/17/06 semicolon instead of a colon. 3/27/06 axd 230 The 3rd-to-last para says that the typeid 6/17/06 test will cost us at runtime, but a good optimizer might eliminate the test. Reword. 3/12/06 txs 234 In comment in last code fragement, "error!" ==> 6/17/06 "error! won't compile". 4/28/06 sdm 247 In last bullet of Item 49, "subsequent" ==> 6/17/06 "associated". 1/ 1/06 kxk 257 Missing comma after declaration of parameter 6/17/06 pMemory in operator delete near middle of page. 11/13/05 jxc 293 Index entry for RAII should refer to page 63 6/17/06 instead of page 66.
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. I added a footnote to this effect. 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 were made for the ninth printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first eight printings.
DATE DATE REPORTED WHO PAGES WHAT FIXED -------- --- ----- ------------------------------------------------ -------- 4/ 7/08 axf xix, "Feher" ==> "Fehér". 7/17/09 xx, 287 7/17/09 sdm 18 In middle code fragment, missing space between 7/17/09 "//" and "cIter". 11/ 4/07 nxd 18-19 The text implies that all by-value returns should 7/17/09 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. 1/ 8/08 jxs 41 In first para, "If getTimeKeeper were to return 7/17/09 a pointer to an AtomicClock object" can be interpreted as suggesting that getTimeKeeper's declaration might be changed, rather than that an invocation of the function might return an object of type AtomicClock. Reword. 8/16/08 lfr 55 As noted in mxr's report of 3/18/07 above, 7/17/09 there is no way to know what deleted pointers point to. This means that the comment in the 3rd para on this page that "the Widget will end up holding a pointer to a deleted Bitmap" is not technically correct. I added a reference to the footnote I added in response to mxr's 3/18/07 report. 8/16/08 lfr 55 We don't copy the original bitmap (*pb), we 7/17/09 copy what will be the new bitmap (*rhs.pb). 7/31/08 exc 56 In the second sentence, reorder the steps to 7/17/09 match the order shown in the comments in the code on the bottom of the previous page. 11/23/08 nxk 72 In last sentence of third prose paragraph, 7/17/09 "Sometime" ==> "Sometimes". 8/ 6/08 ztc 82 In last code fragment, "retVal = ...;" would, 7/17/09 in practice, often be "retVal.reset(...);". Revise to just use "..." as the code on that line. 8/18/08 sdm 131 At the end of second paragraph, add an xref 7/17/09 to Item 25, 6/20/08 oxc 220 In first line, "from int* to double*" ==> 7/17/09 "from double* to int*". 7/2/08 sdm 284 Index entries for "encapsulation, handles and" 7/17/09 288 and "handles, encapsulation and" should refer to page 125 instead of 124. 5/28/08 ms 292 Under "parameters", the "see also" entry for 7/17/09 "passing small objects" should be removed.
The following changes were made for the tenth printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first nine printings.
DATE DATE REPORTED WHO PAGES WHAT FIXED -------- --- ----- ------------------------------------------------ -------- 10/26/09 hgv 47 In last sentence above code example, 2/11/10 "DBConnection destructor" ==> "DBConn destructor". ! 7/19/09 fxw 68 If construction of a std::tr1::shared_ptr throws, 2/11/10 the deleter is automatically called, but in this case, that will yield a call to unlock without a call to lock having been made. Such an unmatched call to unlock will also occur if the call to lock throws. fxw suggests this constructor rewrite: explicit Lock(Mutex *pm) { lock(pm); mutexPtr.reset(pm, unlock); } There was no room in the book for this explanation, so I left the code in the book unchanged, but I added a footnote pointing to this errata entry. 9/18/09 rxk 160 In the top code fragment, the d.mf3(x) call 2/11/10 succeeds, because x (an int) is implicitly converted to a double (the type taken by Base::mf3) for the call. I should clarify this.
The following changes were made for the 12th printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first 11 printings.
DATE DATE REPORTED WHO PAGES WHAT FIXED -------- --- ----- ------------------------------------------------ -------- 2/13/12 sdm 7 In the para discussing interfaces, I revised 2/13/12 the loose definition to include both function names and signatures. 9/30/11 gxx 65 At end of 2nd pargraph, 2/13/12 tr1:shared_ptr ==> tr1::shared_ptr. 9/30/11 gxx 115 In code for Approach A at bottom of page, 2/13/12 semicolon after "some value dependent on i" should not be italicized. 9/30/11 gxx 127 In PrettyMenu's class definition, "Mutex mutex;" 2/13/12 is indented a bit too much. 9/30/11 gxx 145 In Person::Person's parameter list, the second 2/13/12 line ("const Address& addr)") is indented slightly too little. 9/30/11 gxx 147 The colon preceding the RealPerson constructor's 2/13/12 member initialization list is followed by too much white space. 6/23/10 axg 147 Declarations for name, birthDate, and address 2/13/12 don't include "virtual," which, while not required by the language, is contrary to the convention used in the rest of the book. 9/30/11 gxx 175 In the definition of ebg2, the closing parenthesis 2/13/12 just after "_1" should be highlighted. 9/30/11 gxx 188 In code example, declaration for onTick is 2/13/12 indented slightly too far. 6/23/10 axg 201 In the para above the code example, I revised 2/13/12 the wording to mention both function names and signatures. 6/23/10 axg 204 In 3rd para, replace comma after "non-dependent 2/13/12 names" with a period. 9/30/11 gxx 209 In first line of final paragraph, remove space 2/13/12 between "template" and "<>". 9/30/11 gxx 226 At top of page, parameters in doMultiply's 2/13/12 declaration have too much space in front of them. 9/30/11 gxx 230 In 2nd code snippet, the second "typeid(..." line 2/13/12 is a bit shifted to the left. 9/30/11 gxx 231 In all overloads of doAdvance, the second lines of 2/13/12 the parameter lists ("std::...") are indented slightly too little. 6/23/10 axg 242 In declarations for p1 and p2, put asterisks 2/13/12 next to variable names to bring formatting into conformance with convention followed elsewhere in the book. 5/ 6/10 yxt 261 In the definition of operator delete near the 2/13/12 top of the page, omit the word "return". 8/17/11 sdm 263-4 Revised wording in recognition of the adoption of 2/13/12 267 C++11 in September 2011. 281 6/23/10 axg 292 Entry for "pimpl idiom, definition of" should 2/13/12 add pp. 142-143.
The following changes were made for the 13th printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first 12 printings.
DATE DATE REPORTED WHO PAGES WHAT FIXED -------- --- ----- ------------------------------------------------ -------- 5/24/12 jxw 20 Per the advice near the bottom of page 19 to use 3/ 6/13 const parameters whenever possible,position
inoperator[]
should be declaredconst
.
The following changes were made for the 14th printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first 13 printings.
DATE DATE REPORTED WHO PAGES WHAT FIXED -------- --- ----- ------------------------------------------------ -------- sdm xx Add James Weaver to end of first paragraph. 4/10/14
The following changes were made for the 15th printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first 14 printings.
DATE DATE REPORTED WHO PAGES WHAT FIXED -------- --- ----- ------------------------------------------------ -------- 6/17/14 tsc 20 Near top of page, secondoperator[]
should not 8/17/15 be declaredconst
. (This error originated in the 14th printing.) 6/17/14 tsc 21 Allposition
parameters should be declared 8/17/15 23const
. 24
The following changes were made for the 16th printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first 15 printings.
DATE DATE REPORTED WHO PAGES WHAT FIXED -------- --- ----- ------------------------------------------------ -------- 9/15/15 lfr 3 As of C++11, whether symbols from C headers are 5/19/16 visible in the global namespace only or in both the global namespace as well as namespace std is unspecified by the Standard, hence dependent on library implementations. 2/ 7/16 axi 53 In Kindle and Epub editions, the closing paren is 9/27/16 missing in the parameter list declaration for operator+=. 3/ 9/16 sxs 55 Last sentence of 1st para is incorrect: the 5/19/16 Widget won't end up holding a pointer to a deleted object, it will end up holding a pointer to a Bitmap created by copying the (destructed) object reached through a deleted pointer. 6/ 2/16 jxh 107 Bad line break in second code display: comment 6/ 6/16 text "this won't compile" should be on a single line. (This error originated in the preparation of the 12th printing, though it didn't appear until the 15th printing.) 1/ 6/16 pxt 115 Bad line break in code for Approach B near 5/19/16 bottom of page: "i);" wraps, but shouldn't. (This error originated in the 12th printing.) 1/20/16 jxt 120 Reword sentence in first para that reads, "If 5/19/16 Window::onResize modifies the current object..., the current object won't be modified." 1/20/16 pxt 200 Add to second bullet that another factor 5/19/16 contributing to virtuals called on w exhibiting runtime polymorophism is that w is a reference. 3/18/16 jxh 218 In both code examples, pct2 should be renamed 5/19/16 pct to improve the readability of the examples.
The following changes were made for the 17th printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first 16 printings.
DATE DATE REPORTED WHO PAGES WHAT FIXED -------- --- ----- ------------------------------------------------ -------- 6/ 2/16 jxh 254 References to requests for the "wrong" amount of 11/23/16 255 memory should be replaced with references to 292 "unexpected" amounts of memory. 11/23/16 sdm 256 In line after first code display, "two functions 11/23/16 are called" => "two function calls take place". 6/ 2/16 jxh 259 Per the convention mentioned on page 257 (as 11/23/16 well as the Widget class definition on that page), the "normal" operator delete at class scope should take a std::size_t parameter.
The following changes were made for the 19th printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first 18 printings.
DATE DATE REPORTED WHO PAGES WHAT FIXED -------- --- ----- ------------------------------------------------ -------- 11/27/17 sdm Copy- The 18th printing has incorrect information 1/16/18 right about the printing number and date. The printing has "18 17" as the last line on the page, but the line above says it's the 17th printing. The printing date is shown as January 2017, but the actual printing date is August 2017. 9/10/17 lfr 261 StandardNewDeleteForms' version of nothrow 1/18/18 delete should invoke the global nothrow delete instead of the global "normal" delete. That is, it should be defined like this: static void operator delete(void *pMemory, const std::nothrow_t& nt) throw() { ::operator delete(pMemory, nt); }
The following changes have been proposed, but have not yet been reviewed and published:
DATE DATE REPORTED WHO PAGES WHAT FIXED -------- --- ----- ------------------------------------------------ -------- 6/21/21 gxl 76 In 2nd para, "object-managing resources" ==> "resource-managing objects". 6/21/21 gxl 115 In last para, "is it be better" ==> "is it better".
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.)
3/19/11 lfr 4 The official C++ definition of "signature" includes the
name of the function, but my definition does not.
That's true, and it's because I want to use the term
in Item 35, where the name of the function is
superfluous. Unfortunately, there are other Items
where I use the term "signature," but the name is
important (e.g., Item 41). The C++03 standard
specifies that a function signature is comprised of its
name and parameter types, but TR1 indroduces the idea
of a "call signature," which is the same as what I call
a signature. There is no official name for a signature
that includes both a function's name and its return
type, but that's also a useful idea, one that I use in
Item 52. The bottom line is that there are at least
three useful definitions of "signature," and I should
probably be clearer about my meaning of the term when I
use it.
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."
2/12/18 exk 14 const objects have internal linkage, so const objects
defined in a header generally end up occupying space
proportional to the number of translation units that
include the header. A const object of type T defined in a
header that's included in n translation units will
typically use space for n objects of type T in the final
executable. (Compilers and linkers may optimize some
objects away, but the conditions under which such
optimizations can be performed are restricted.)
To avoid getting multiple copies of these objects,
declare them extern, and provide a single definition in
one .cpp file, e.g.:
extern const std::string authorName; // in header
extern const std::string authorName("Scott Meyers"); // in one
// .cpp file
In C++17, a simpler solution is to declare such objects
inline in the header:
inline const std::string authorName("Scott Meyers"); // C++17
1/25/15 pxm Item 3 Applying const to typedefs for pointer types can be
confusing:
typedef int* PInt;
const PInt p = 0; // p is a const ptr to int,
// not a ptr to const int
For details and an explanation of why this issue
has led some people to prefer to put const after
the type instead of before it (as I show on page
18 of the book), consult this article.
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.
! 6/30/11 pth 24-25 The approach shown works only when the const and
non-const versions of operator[] do exactly the
same thing. The sample code on page 24 works under
Visual C++ 10, for example, but it fails under gcc
4.5. That's because TextBlock's operator[] calls
std::string's operator[], and the const and
non-const versions of std::string::operator[] are
the same under VC10, but different under gcc 4.5.
(gcc reference- counts its strings. VC10 does
not.)
The general conclusion is that eliminating
duplication between const and non-const member
functions calls for more than just having the
non-const version call the const version. You must
also perform the analysis to establish that the
resulting behavior is correct.
9/10/14 pyg 27-29 In class ABEntry, "thePhones" should be named something
more like "thePhoneNumbers", and the constructor's
"phones" parameter should be named something more like
"phoneNumbers".
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).
10/26/09 hgv Item 8 The names "DBConnection" and "DBConn" are similar enough
that they are likely to cause confusion. They should be
given more distinct names.
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/20/11 pth Item 10 The Item suggests that it's necessary to return a
reference to the class in order to enable assignment
chaining, but this isn't true. Assignment chaining
would also work if operator= returned an object by
value, i.e., if Widget::operator= returned a Widget (as
opposed to a Widget&). This would be less
efficient, however.
10/17/15 hxa 67-68 Adding a tr1::shared_ptr to a class like Lock has
significant side effects: the revised class can
throw exceptions, and tr1::shared_ptr allocates and
deallocates memory. In this case, those costs may
outweigh any benefit to be gained from making the
Lock class copyable.
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.
5/23/08 mmm 89-90 The discussion of when pass-by-value can be appropriate
fails to mention that when such parameters are not
supposed to be modified inside the function, they should
be passed as consts (per Item 3).
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."
6/ 2/16 jxh Item 25 Just as Item 12 explains that copying operations should
copy all parts of an object (including base class parts),
Item 25 should explain that swap functions should swap all
parts of an object (including base class parts).
Unfortunately, I don't see a graceful way to add this to
the treatment in the book, so this errata list entry will
have to suffice.
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 clone
and in factory methods.
8/23/05 bgn 126 The example does not make the case very well, because even
if upperLeft and lowerRight returned Point objects by
value, pUpperLeft would still dangle at the end of the
statement.
12/ 4/16 bxp 133 bxp remarks that a partial molar pregnancy could be viewed as
a partial pregnancy. Strictly speaking, however, it's just a
kind of pregnancy. Females with a partial (or full)
molar pregnancy are pregnant.
8/24/05 bgn Item 31 "We work on embedded systems, but often we want to run our
code on PC's in a simulation environment, or perhaps
perform testing before our custom hardware has been built.
So for those hardware dependent classes (such as modems,
serial ports, etc) we sometimes use the pimpl idiom and
pick a different implementation file (.cpp file) in our
makefiles at build time. This let's us seamlessly run our
code in multiple environments w/o resorting to making base
classes, using inheritance, and making factory
functions. We've gotten a lot of mileage out of that."
9/ 2/05 bxm Item 31 "All our Interfaces have a unique Prefix,.e.g class
IPerson, class IShape, etc, so we prefix all Interfaces
with I. This is simple but very effective. A programmer
does NOT have to look into the class and see if there is
a pure virtual function. The name says all ;-)
We have created a new keyword IMPLEMENTS for class
implementers so it looks very like java:
#define IMPLEMENTS public /* or virtual public */
E.g. in c++ we write: class PersonImpl : IMPLEMENTS
IPerson. So the programmer can distinguish between
public inheritance and interface inheritance. You can do
the same with EXTENDS when interfaces inherit from
interfaces (in C++)..."
10/ 5/05 jsl 175 In the call to tr1::bind, currentLevel is passed by
value. A (typically preferable) alternative is to pass a
pointer to currentLevel.
I (Scott) also note that another alternative -- one in
accord with Item 20 -- would be to pass currentLevel by
reference-to-const. This can be done using tr1::cref,
which is not discussed in the book. The call would look
like this:
std::tr1::bind(&GameLevel::health,
std::tr1::cref(currentLevel), _1);
10/28/12 yxr 189 Another advantage of using composition over private
inheritance (beyond controlling virtual function
redefinitions and minimizing compilation
dependencies) is that with composition, it would be
possible for a Widget to have more than one Timer
associated with it.
8/31/06 bxm Item 41 One way to make implicit interfaces explicit is to use
the Boost Concept Check Library.
6/23/10 axg 198 Declarations for valueDelimOpen and valueDelimClose
don't include "virtual," which, while not required
by the language, is contrary to the convention used
in the rest of the book. (This is true, but adding
"virtual" would cause serious reformatting issues
on this page, so I'm leaving the code as is.)
1/28/10 tdh 202 The statement that "T must support a size member
function" is not rigorously true. It could be
that T has a public data member that is a
function object that can be called with zero
arguments.
3/18/16 jxh 214 Instead of having SquareMatrix privately inherit from
SquareMatrixBase, SquareMatrixBase could be made private
in SquareMatrix, and SquareMatrix could declare a
SquareMatrixBase data member. (In that case,
SquareMatrixBase's member functions would need to be
public.) The resulting design would resember that shown
on page 189 for Widget and WidgetTimer and would better
adhere to the advice of Item 39, which says to use
private inheritance only when you must.
12/10/07 sxo 226 The doMultiply template can be eliminated by structuring
the code as follows:
template<typename T> class Rational;
template<typename T>
const Rational<T> operator*(const Rational<T> &lhs,
const Rational<T> &rhs);
template<typename T>
class Rational {
// declaration/definition of non-templated operator
friend const Rational<T> operator*(const Rational<T> &lhs,
const Rational<T> &rhs)
{
return operator*<T>(lhs, rhs);
}
...
};
// definition of templated operator
template<typename T>
const Rational<T> operator*(const Rational<T> &lhs,
const Rational<T> &rhs)
{
return Rational<T>(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}
6/23/10 axg Item 47 The text should explain when I use iterator tags as
naked type names and when I use them to create anonymous
objects. For example, on page 231, I use naked type
names to create unnamed function parameters, but on
page 232, I use
std::iterator_traits<IterT>::iterator_category to
create an anonymous object to pass to doAdvance.
12/10/07 sxo 231-232 The tag arguments passed to the doAdvance functions may,
depending on compiler/linker optimizations, incur a
runtime cost. Such cost can be eliminated by writing the
code this way:
// declaration for helper class
template<typename IterT, typename DistT,
typename TagT = typename std::iterator_traits<IterT>::iterator_category>
class Advance;
// specialization of above for random access iterators
template<typename IterT, typename DistT>
class Advance<IterT, DistT, std::random_access_iterator_tag> {
public:
static void DoAdvance(IterT &iter, DistT d)
{ iter += d; }
};
... // other specializations go here
template<typename IterT, typename DistT>
void advance(IterT &iter, DistT d)
{
Advance<IterT, DistT>::DoAdvance(iter, d);
}
3/24/07 hxs 235 In 2nd para, the comment that TMP allows for the declaration
of variables is potentially misleading, because such "variables"
can't vary: once they are initialized to a value, that value can
never change. TMP is a functional language, hence offers no
support for assignment. TMP variables are akin to const
"variables" in C++.
4/20/06 jeh 243 NewHandlerHolder would be easier for clients to use if
they passed the new new_handler instead of the old one,
i.e., if the NewHandlerHolder constructor called
set_new_handler itself. (In this case, the class might be
better named something like NewHandlerInstaller, instead.)
4/ 4/12 sdm 260-1 It might be preferable to have Widget privately inhert
from StandardNewDeleteForms, because that would prevent
inadvertant Widget* ==> StandardNewDeleteForms*
conversions. Technically, however, there is an "isa"
relationship between these classes, so public
inheritance is not incorrect. Another possible
improvement is to give StandardNewDeleteForms a
protected destructor.
11/23/16 sdm 260 Page 257 notes that the "typical" normal signature for
class-specific operator delete includes a std::size_t
parameter, but this parameter is actually optional, and
in the "normal" version of operator delete in
StandardNewDeleteForms, there is no need for it (as the
implementation makes clear). That's why the "normal"
operator delete in StandardNewDeleteForms has no
std::size_t parameter.
10/22/05 sdm 265 Technically, tr1::weak_ptr isn't a smart pointer,
because it doesn't overload operator->.
11/13/05 mxd NA It would be nice to have an Item exhorting readers to
use a lint-like tool as part of their development process.
1/13/11 mym NA "At the end of each item, you provided key take away points in
bulleted lists. I would like to see the collective take-
aways from the items together at the end of the book as
an appendix. That way we can get a concise summary
together as a recap, and do not have to flip through the
book for each items summary."
Who's who:
jxr = Jason Ross clm = Cameron Mac Minn rxy = Robert Yokota jeh = John Hershberger exa = Ejaz Anwer txs = Thomas Schell mxm = Marc Mutz axd = Alex Dumov dxe = Dick Eimers bp = Balog Pal ixl = Idan Lupinsky pxg = Paul Grenyer bxm = Bernhard Merkle yxf = Yukitoshi Fujimura gwj = G. Wade Johnson nxd = Niels Dekker gxk = Gerhard Kreuzer lfr = Fraser Ross tdh = T. David Hudson bxs = Balbir Singh clt = Clovis Tondo hgv = Harsh Gaurav Vangani axf = Attila Fehér jxm = Jürgen Messerer bgn = Brian Neal mxr = Mike Rizzi jds = J. Daniel Smith ahh = Alex Howlett pxh = Phillip Hellewell sxf = Solomon Foster wxv = Walter Vannini dxs = David Solomon mxs = Marcin Sochacki hxs = Hendrik Schober jsl = Joshua Lehrer pxw = Peter Weinert ejx = Ed Ji Xihuang mxh = Miaohua jxc = Jiongxiong Chen bxj = Brian Johnson mxd = Michael Drumheller dmr = Martin Rottinger axh = Andrew Henrick sxo = Sergei Otarov vxs = Vincent Stojanov ms = Molly Sharp kxk = Ken Kobayashi oxc = Owen Chu ser = Eldar Ronen mmm = Merlin Meyer-Mitchell vxp = Vasily Poshehonov exc = Effeer Chen awo = Tony Oliver ztc = Zachary Cohen jxs = Joe Suzow nxk = Nate Kohl fxw = Florian Weimer rxk = Richard Kinder scd = Stephen C. Dewhurst yxt = Yuxing Tian axg = Alexandros Gezerlis mym = Monir Mozumder pth = Premkumar Thoppae gxx = Guilliam Xavier jxw = James Weaver yxr = Yuval Ronen tsc = Tim St. Clair pyg = Piotr Gregor pxm = Patrick Matters hxa = Hasan Alayli pxt = Peter Torr jxt = Jochen Taeschner axi = Andrew Ircha sxs = Santanu Sen jxh = Jeff Hurchalla bxp = Bozorgmehr Pouyeh exk = Erich Krey gxl = Glenn Lacki
From here you may wish to visit the Amazon Page for Effective C++, Third Edition.