Friday, September 14, 2001

Updated errata lists; article in CUJ; upcoming seminar reports

Topics this time:
- EC++ and MEC++ Errata Lists have been updated.
- I have an article in the October CUJ.
- Reports from "THE C++ Seminar" to be posted (but not here).


Updated Errata Lists:

I just finished updating the errata lists for Effective C++ and More
Effective C++. (Both books are due for reprints later this month, so the
time was ripe.) New entries to the errata lists are at the end of this
message. The full lists are available at the usual URLs:

EC++: http://www.aristeia.com/BookErrata/ec++2e-errata_frames.html
MEC++: http://www.aristeia.com/BookErrata/mec++-errata_frames.html


Article in the October CUJ:

The October CUJ contains a slightly-modified version of Effective STL's
Item 43, "Prefer Algorithm Calls to Hand-Written Loops." (The article
title is one of the things that is slightly modified compared to the book.)
As an aside, the December CUJ is slated to run ESTL Item 45, but don't
believe it until you see it, because publication plans have been known to
change at the last minute.


Reports from "THE C++ Seminar":

The special C++ Seminar hosted by me, Herb Sutter, Dan Saks, Steve
Dewhurst, and Andrei Alexandrescu runs next Monday-Wednesday. If you're
one of the people who would have liked to attend, but couldn't, or if
you're just curious about what such an event will be like (I am), we plan
to post daily informal summaries to the seminar's mailing list. (They will
NOT be posted to this list). You can sign up for the seminar's mailing
list at http://groups.yahoo.com/group/cpp_seminar/.


Finally, I truly hope that you and yours were not personally affected by
Tuesday's indescribable horrors. Words do not exist for how I feel, so
I'll just say this: I wish you all the best.

Scott

===============================================================================
New Entries for the EC++ Errata List
===============================================================================
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
3/ 7/01 das xix "Dave Smallberg" ==> "David Smallberg" 9/10/01
254

! 8/25/00 pm 68 In operator=, "*ptr = *rhs.ptr;" ==> 9/10/01
"ptr = rhs.ptr;" Modify the comment
accordingly.

8/15/00 cb 104 Eliminate the first prose paragraph on this page. 9/10/01
105 (When I originally wrote the paragraph for the
first edition of EC++, the example involved
string objects, not rational numbers, and for
strings, the situation was different. When I
changed the class for the example, I failed to
recognize that the words no longer made sense
for the example.) To avoid too unbalanced a
page, I moved the break between pages 104 and 105.

8/16/00 cb 124 At the end of the 2nd to last sentence on the 9/10/01
page, it would be helpful to xref Item 21's
explanation that the data pointed to by a pointer
in a const object is not automatically const.

! 2/10/00 ic 212 A class declaring no operator& function(s) 9/10/01
cxh 213 does NOT have them implicitly declared. Rather,
245 compilers use the built-in address-of operator
246 whenever "&" is applied to an object of that
type. This behavior, in turn, is technically
not an application of a global operator&
function. Rather, it is a use of a built-in
operator.
I eliminated mention of operator& as an
automatically generated function and adjusted the
index to eliminate entries for the removed
material.

! 4/ 8/01 hs 228 The Standardization Committee has now ruled that 9/10/01
library implementers must declare string as
defined in the Standard, so my comment about
their being allowed to add extra parameters is
incorrect. However, the Standard continues
to forbid you from declaring string yourself.
The advice in this Item stands (#include
<string> instead of trying to declare the string
type yourself), but the rationale for that
advice is no longer valid.

Interesting Comments:

DATE
REPORTED WHO PAGES WHAT
-------- --- ----- -----------------------------------------------------------
8/ 8/00 cb 15 Observes cb:

It appears that the Microsoft Visual C++ 6.0 SP3 compiler
requires the "enum hack" to work. Interesting, since it
is stated that "Unless you're dealing with compilers of
primarily historical interest (i.e., those written before
1995), you shouldn't have to use the enum hack."

It appears that Visual C++ 6 was released in mid-1998.
Sigh.

6/20/01 cbs Items cbs points out that the code in Item 30 isn't thread safe,
sdm 7,8,10 but the problem exists in Items 8 and 10, too. In fact, I
fail to consider thread-safety throughout the book,
something I can argue is excusable only because C++ itself
fails to consider threading issues. You'll see other
comments on how threading interact with my advice in
various places in this errata list. If I ever write a
third edition, I'll be sure to take threading issues into
account.

6/ 5/01 sdm 67 In the prose following the third code example, it's not
technically true that the temporary is const. Rather, the
temporary is an rvalue, and C++ forbids binding references
to rvalues unless they are references to const. This is
not a bug in the book. Rather, it is a deliberate attempt
to spare you from having to know about rvalues, because
they're more confusing than helpful, especially if you know
the rules for rvalues in C. Setting aside technicalities,
the information on this page is accurate in its
essentials.

6/22/01 sdm Item 19 The bulleted summary at the end of this Item no longer
reflects my full thinking on this topic. For an updated
version of the summary as well as an explanation of how and
why things changed, please read my February 2000 href="http://www.cuj.com/" target="_top">C/C++
Users Journal
article, href="http://www.cuj.com/articles/2000/0002/0002c/0002c.htm" target="_top">"How
non-member functions improve
encapsulation
."

2/19/01 sdm Item 19 When templates enter the picture, things become more
complicated. Compilers must not only perform type
conversions on actual parameters, they must also perform
template type deduction to determine the types of formal
parameters. The end result is that templates for functions
like operator+ should still be non-members, but they need
to be defined as friends inside the class they work with in
order to be instantiated correctly. For details, consult
the February 2000 thread in comp.std.c++ with the title,
href="http://groups.google.com/groups?hl=en&safe=off&threadm=zdv176.950799804%40\
zam475&rnum=1&prev=/groups%3Fas_epq%3Dautomatic%2520conversion%2520with%2520func\
tion%2520templates%26as_ugroup%3Dcomp.std.c%252b%252b%26as_drrb%3Db%26as_mind%3D\
29%26as_minm%3D1%26as_miny%3D2000%26as_maxd%3D5%26as_maxm%3D9%26as_maxy%3D2001%2\
6num%3D100" target="_top">"Automatic conversion with function templates?"

It was
initiated by Bernd Mohr.

9/17/00 ch Item 20 Notes ch:

Objects are state machines. An Object would lose control
of its own states if you allow public data members. This
makes it for instance impossible to implement a typical
Observer Pattern in an object oriented way. The problems
get really nasty for objects with public data members
when living in a multithreaded environment ....

6/11/00 tm 99 In general, it's dangerous for a function to return a
reference to a parameter passed by reference-to-const,
because the parameter may have been bound to a temporary
object that will be destroyed at the end of the call. For
example, consider this use of returnStudent:

Student makeStudent(); // function declaration

const Student& cs = returnStudent(makeStudent());

returnStudent's parameter s is bound to the temporary
object returned from makeStudent. returnStudent then
returns that reference, which is used to initialize another
reference, cs. Unfortunately, once cs is initialized, the
temporary returned from makeStudent is destroyed, and cs is
a dangling reference -- it refers to an object that no
longer exists. (Note the similarity to the problem
discussed on pages 127-128.)

2/27/01 ph Item 23 Once you've resigned yourself to returning a new object
from functions like operator*, you'll naturally look for
ways to make that as cheap as possible. One way to do that
is to return a pointer posing as an object.
The following comment was sent regarding Item 20 of href="http://www.awl.com/cseng/titles/0-201-63371-X/" target="_blank">More
Effective C++
, but it's relevant to Item 23 of
Effective
C++
, too:

We faced the problem of getting large float and int
arrays from a database. The dimension of the array
depended on the time interval passed as an argument to
the reading method. Clearly, we had to return an object,
and we couldn't rely upon return value optimization
[which is the subject of MEC++ Item 20].

Our solution was to return an auto_ptr<Array<T>
> instead
of an Array<T>. This way, we had the advantage of
returning something as light as a pointer without the
problem of potential memory leaks. The only drawback was
a slightly heavier syntax but it was worth it.

I don't think this is a solution for the method operator*
that you used in item 20 but many other methods that have
to return large objects may benefit from it.


===============================================================================
New Entries for the MEC++ Errata List
===============================================================================
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
3/30/01 sdm 2 Material in the book is based on the final C++
Standard, not the DIS.

9/ 6/00 bp 33 In accord with my advice in Item 21 of Effective
C++ to "use const whenever possible," oldValue
should be declared const in the code example at
the top of the page.

2/21/01 wds 58 In second paragraph, "initializationof" ==>
"initialization of".

! 8/15/00 wcm 142 For consistency with the changes I made on
144 6/6/98 (see above), the Counted template should
have objectCount return a size_t instead of an int,
and numObjects should be of type size_t, not int.

Interesting Comments:

DATE
REPORTED WHO PAGES WHAT
-------- --- ----- -----------------------------------------------------------
7/31/00 cw 208ff Notes cw:

While href="http://www.aristeia.com/BookErrata/M29Source.html"
target="_blank">exploring your reference counting code
, I realized
that there is no method allowing a user of the RCIPtr
class to mark the CountHolder unshareable. I believe such
a method is essential to the correct operation of the
RCIPtr when a user is confronted with making a some one
else's class reference counted and that class has methods
which return references to the the internal parts of the
class.

In your widget example, if there were a method
int& Widget::getThat(), the corresponding RCWidget method
would have to make a call to a RCIPtr::markUnshareable()
method that would call the RCObject::markUnshareable()
method. This would prevent the int reference from being
used to alter a widget that is held by more than one
RCWidget.
http://www.aristeia.com/BookErrata/M29Source.html

2/27/01 ph Item 20 Writes ph:

We faced the problem of getting large float and int
arrays from a database. The dimension of the array
depended on the time interval passed as an argument to
the reading method. Clearly, we had to return an object,
and we couldn't rely upon return value optimization.

Our solution was to return an auto_ptr<Array<T>
> instead
of an Array<T>. This way, we had the advantage of
returning something as light as a pointer without the
problem of potential memory leaks. The only drawback was
a slightly heavier syntax but it was worth it.

I don't think this is a solution for the method operator*
that you used in item 20 but many other methods that have
to return large objects may benefit from it.


4/27/97 sdm Item 30 In a posting to comp.lang.c++.moderated posting of
4/25/97, Brian Parker writes:

One problem with the use of proxies that I have found that
is not discussed in "More Effective C++" is when they are
used for templated types e.g. for complex... . In
this scenario, when calling template functions that take
complex (e.g. conj() et al) with a returned proxy, the
proxy is not converted to a complex but instead a
template argument deduction failure results.

For further information on this observation, look up the
thread, href="http://groups.google.com/groups?hl=en&threadm=5jq51o%2479g%40netlab.cs.rpi\
.edu&rnum=1&prev=/groups%3Fas_epq%3Done%2520problem%2520with%2520the%2520use%252\
0of%2520proxies%26as_ugroup%3Dcomp.lang.c%252b%252b.moderated%26as_drrb%3Db%26as\
_mind%3D29%26as_minm%3D3%26as_miny%3D1997%26as_maxd%3D13%26as_maxm%3D9%26as_maxy\
%3D1997">"lvalue/rvalue, non-const/const"
initiated by Daniel
Hempel on April 21, 1997.

8/ 5/01 sdm Item 31 For a more contemporary treatment of multiple dispatch
than I give in Item 31, check out chapter 11 of Andrei
Alexandrescu's excellent href="http://www.awl.com/cseng/titles/0-201-70431-5/">Modern C++
Design
. It's the most
thorough and up-to-date examination of the topic that I know
of.

No comments: