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:

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

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

   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

   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

   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

   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

   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.

  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 tempDir, initialization of td is missing       6/17/06
                      "( params )".

   1/25/06 bxm    47  Code for ~DBConn is missing a close } for the     6/17/06
                      opening if statement, and the block controlled
                      by the if 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

   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

  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

   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

   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

   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 

   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

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

   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
                        fxw suggests this constructor rewrite:

                          explicit Lock(Mutex *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

   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.

   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 in
                      operator[] should be declared const.

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, second operator[] should not    8/17/15
                      be declared const. (This error originated in
                      the 14th printing.)

   6/17/14 tsc    21  All position parameters should be declared        8/17/15
                  23  const.

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 

   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 

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.

   -------- --- ------- ----------------------------------------------------------
    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

    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

                          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
                          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

   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.

    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

   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::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

    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> {
                            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.