Scott Meyers
Modification History and Errata List for Effective C++, Third Edition
Last Updated July 3, 2008
by Scott Meyers
Note: This document applies to only the third edition of Effective C++. Errata for earlier editions of the book are available as follows:
What follows are my notes on what I've changed in the third edition of Effective C++ since its original publication (i.e., since its first printing) and what I believe may need to be changed in future printings. Most of the changes (or prospective changes) are cosmetic and don't affect the technical content of the book. To distinguish those modifications that do affect technical material, I precede those entries with an exclamation mark ("!") and display them in red.
Each entry includes the following information:
- 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 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
"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.
5/10/07 sdm 107 In second code fragment, move "this won't compile" 1/28/08
comment to the line trying to access the
pImpl pointers.
9/15/07 dmr 118 Should mention that the two cast forms shown at 1/28/08
the top of the page yield identical behavior,
e.g., both create temporary Widget objects.
9/15/07 dmr 125 In 1st para, comma preceding the parenthetical 1/28/08
comment should be a period.
9/15/07 dmr 145 In comment at top of page, "exactly the same 1/28/08
member functions" ==> "exactly the same public
member functions".
! 7/28/07 mxh 158 In first line on page, "containing Base" ==> 1/28/08
"containing Derived".
!12/22/07 lfr 193 In 1st para, "checkOut" is ambiguous during name 1/28/08
lookup, not overload resolution; and the two
"checkOut" functions are not equally good
matches, because one is const and one is not.
7/17/07 mxr 197 Class definition of PersonInfo should match that 1/28/08
shown on page 195.
10/ 3/07 bxj 239 3rd para should make clear that the new-handler 1/28/08
is a global resource and thus subject to the
thread-safety issues that apply to all such
resources.
The following changes have been proposed but have not yet been published:
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
4/ 7/08 axf xix, "Feher" ==> "Fehér".
xx,
287
11/ 4/07 nxd 18-19 The text implies that all by-value returns should
be const, but cases where non-const by-value
returns are good design are not difficult to find,
e.g., return types of std::vector<T> where callers
will use swap with an empty vector to "grab" the
return value contents without copying them.
Reword.
5/23/08 mmm 89-90 The discussion of when pass-by-value can be
appropriate should make clear that when such
parameters are not supposed to be modified inside
the function, they should be passed as consts
(per Item 3).
6/20/08 oxc 220 In first line, "from int* to double*" ==>
"from double* to int*".
7/2/08 sdm 284 Index entries for "encapsulation, handles and"
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 5/??/08
"passing small objects" should be removed.
What follows are interesting comments about the material in Effective C++, Third Edition, but I don't expect to be able to modify the book to take these comments into account until (if ever) I write a fourth edition.
DATE
REPORTED WHO PAGES WHAT
-------- --- ------- ----------------------------------------------------------
9/26/06 jxm 2 The book says it limits itself to standard C++, but the
book also shows use of non-standard libraries such as TR1
and Boost. (This is true, but the book uses no
non-standard language features, only portable libraries
presenting standard-conforming interfaces.)
5/ 6/05 exa Item 2 "In one of my recent projects, I have to use 2 third party
libraries and both of them had a symbol define with the
same name, like in one library
#define SOMETHING 1
and in another
#define SOMETHING 2
now, while compiling, the second one overrights the first
one. I tried with the namespace, but still no luck, later
on, I've to do the manual stuff. At that time, I really
appreciated your Item about avoiding #define.
I didn't find this specific issue in your item (and not
anywhere else also), so I'm just forwarding it to you."
11/ 2/07 nxd 18-19 Declaring by-value function return values const will
prevent their being bound to rvalue references in C++0x.
Because rvalue references are designed to help improve
the efficiency of C++ code, it's important to take
into account the interaction of const return values
and the initialization of rvalue references when
specifying function signatures.
9/12/05 pxh 24 Unfortunately, even const_cast can't be used to cast a
const_iterator to an iterator. For details, consult Item
27 of Effective STL (available online as part of
my June 2001 CUJ article, where it's known as Guideline 2)
as well as the newsgroup discussion of the matter.
11/21/06 pxw 32 pxw reports that some compilers (notably Sun's) won't
inline functions containing static data. Compilers
don't have to inline anything, but if inlining is
important to you, be on the lookout for this issue.
7/25/05 tdh 33-34 Using functions to return references to local static
objects is a good way to avoid referring to uninitialized
objects, but local static objects are automatically
destroyed (in the reverse order in which they were
constructed) at program shutdown, and this means that it
is possible for the destructor of one local static object
to refer to another local static object that has already
been destroyed. [For a good discussion of this problem
and two possible ways to deal with it, consult sections
6.5-6.8 of Andrei Alexandrescu's Modern C++ Design.
--Scott]
7/28/06 lfr Item 6 Inheriting from a base class like Uncopyable or
boost::noncopyable can be more convenient than manually
declaring the copying functions private, because the base
class does not disable the automatic generation of a
default constructor, but manually declaring a copy
constructor does (per Item 5).
11/26/06 nxd Item 6 If a class C declares the copying functions private and
defines a function f that performs copying, but f is never
called, the code will compile and link. (If f is called,
the code will not compile.) To prevent this (unlikely)
problem, nxd suggests:
- Have C's operator= return an incomplete type.
- Declare C's copy constructor explicit (i.e., prefix it
with the "explicit" keyword).
9/ 8/05 wxv 47 wxv notes that if a client calls DBConn::close, and that
2/ 3/07 sxf call throws an exception, the database did not close
successfully, but in some libraries, calling close on it
again (in the DBConn destructor) would be harmful. It
might thus be better to use an enum instead of a bool to
keep track of the state of the database, e.g.,
enum DBStatus { Open, Closed, AttemptToCloseThrew };
sxf argues that this approach leads to the destructor
trying to close the connection again if the call to close
throws, and that puts us back in our original position.
A better design might be to change the enum to
enum DBStatus { Open, CloseAttempted };
and not try to invoke close if it's already been called.
6/27/06 pxg Item 15 A way to minimize the need to access raw resources is
to wrap legacy APIs with ones that know about resource
managers. For example, daysHeld (at the bottom of
page 69) and releasefont (at the bottom of page 70) could
be augmented with these functions, which clients could
then call with resource-managing objects:
int daysHeld(const std::auto_ptr<Investment> p)
{ return daysHeld(p.get()); }
void releaseFont(Font f) { f.get(); }
6/12/05 sdm Item 17 The reasoning in this Item applies to more than just
dynamically allocated memory. It should be revised to
apply to resource acquisition in general.
6/19/05 mxm Item 23 mxm notes that this Item doesn't discuss the ramifications
of the different calling syntaxes for member and non-member
functions. However, I do discuss this issue in the
article-length treatment of this topic. Scan for "Syntax Issues.")
8/26/07 mxd Item 23 "A C++ pattern that I have often seen is that there'd be a
big hairy class with a ton of methods that all work
together to get some giant job done. If a certain style
is followed, the logic of that job can be very hard to
follow. That style is having MethodA do a ton of work and
then call MethodB (and possibly MethodC, MethodD, ...,
MethodZ) with few if any arguments to the call. The
methods are all of the same class, so basically they are
handing off "arguments" to one another by what amounts to
file-global variables: the member variables of the class.
In my mind the self-documenting quality of a piece of code
is carried almost entirely on the shoulders of the names
of functions and arguments passed to them. If you throw
away the arguments you lose half the visual meaning behind
every method call, and it makes the code terribly hard to
read. In other words, whenever you see MethodA call
MethodB in the same class, all you know vis-à-vis the
data flow is that it involves (a) the arguments passed
(if any) and (b) a potentially arbitrary subset of the
member variables. It’s just plain global-variables
lite. And it is avoided completely if you stick to
non-member, non-friend functions as much as possible."
7/19/06 nxd 110-111 Putting "using std::swap;" in a function calling swap is
not sufficient to ensure that the proper swap will always be
called. For details, consult this Usenet thread devoted to this topic.
The C++ Standardization committee has addressed the broader issue
present here via a defect report on the matter.
6/ 7/07 clt 115-116 If the operand to the assignment in loop Approach A is
not of a type taken by a Widget assignment operator, a
temporary may be introduced. If this happens, each
call to Widget's operator= will incur the cost of a
temporary construction and destruction.
6/29/05 dxe Item 27 One way to reduce the need for downcasts is to take
advantage of C++'s support for covariant return types in
member functions like 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.
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);
8/31/06 bxm Item 41 In C++0x, it is highly likely that a new language feature
known as "concepts" will make it possible to make implicit
interfaces explicit. Until such a feature exists, it is
possible to use the Boost Concept Check Library for this
purpose.
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());
}
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.)
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.
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 awo = Tony Oliver
From here you may wish to visit the Amazon Page for Effective C++, Third Edition.
