C++ Distilled

by Ira Pohl  

Addison-Wesley ISBN 0-201-69587-1

C++ Distilled: A Concise ANSI/ISO Reference and Style Guide is a concise roadmap and style guide to C++ and at just over 200 pages it is slim and easy to use.

C++ Distilled selectively previews the proposed ANSI standard C++ language and includes many programming tips. It is easily used with any C++ programming book, but is especially suitable when used with one of my other books, Object-Oriented Programming Using C++, Second edition, C++ for C Programmers, Second or Third Edition, C++ for Pascal Programmers, Second Edition or C++ for Fortran Programmers.

Each section has the syntax, semantics, and examples of the language element and there are end-of-section style and programming tips. Heuristics and style tips provide experience-based suggestions on how to properly use a language feature.

Most programming is done by imitation of existing code and idioms. It is far easier to see a typical template than to read a 30-page description by language lawyers on all the intricacies. Therefore, the examples both within the book, and accessible at Addison Wesley Longman's website, are intended to exhibit good programming style. These examples use Dr. P's prescriptions and programming tips which are a distillation of considerable professional practice.

This book is a roadmap so that you do not get lost in the ANSI C++ byways. Although it is not a substitute for the ANSI standard, which is approximately 700 detailed technically dense pages, most programmers do not need such detail. Indeed, many of the features detailed in the standard are highly specialized and little used. Most programmers need to be able to quickly review some syntax or semantics that they have not recently used. C++ has many recent additions including STL, namespaces, RTTI, and the bool type. These can be used readily by someone already proficient in basic C++, but most books have yet to treat these topics. This book can provide a handy guide to these new constructs. Especially useful should be basic examples and information on STL container classes and generic algorithms.

You can buy this book online through Barnes and Noble.

The C++ code examples in the book are available in several forms. To get to the unpacked version for any system, or to get individual program files, you can use the FTP directory (www.cse.ucsc.edu/~pohl/DRP/). Files are also available in zip form for Windows users and compressed tar form for UNIX users.


Additional C++ Code Examples

Ira has provided additional code to demonstrate dynamic cast, complete clock program, multiple inheritance, mutable members, string constructors, and rvalue vs. lvalue.


Errata

Changes made in later printings are followed by a comment indicating the date.

Caveats: Some standard libraries may have been modified since this book was written and the function prototypes may differ from what is available on your compiler. Check your compiler vendor for the correct prototypes.

Notations: p425 means page 425  
                            +8 means 8 lines from top 
                             -7 means 7 lines from bottom

If you encounter errata in this book not listed here, please contact Ira Pohl via email at pohl@cse.ucsc.edu with your errata. You will be cited in the correction if you are the first to report it.

Acknowledgements: Thanks to George Belotsky for giving me a first detailed list of errata. Thanks also to Jeffery Peden for his comments.

 


p v (C. L. Tondo) line -9: The examples both within the book are ...

Needs to be: The examples both within the book, and accessible at Addison-Wesley's web site are ...

(The above correction has been made in printings after December 1997)


p2 (Dolsberry) line 3: wrong double quote style.

Needs to be: "\nGreatest Common Divisor"

(The above correction has been made in printings after December 1997)


p. 9 (Paul Sevinc) line -4: "greater precision" would be more acurately "greater range".

Needs to be: long constants have greater range ...


p11 (Dolsberry) String table constants have several wrong fonts for quotes.

Needs to be: '\0' on table entry 1

'O' 'O' 'P' ' ' '4' 'M' 'E' '\0' on table entry 2

"This is a single string, " on table entry 4

(The above correction has been made in printings after December 1997) p11 (C. L. Tondo) line -5: The closing ] in bus_stops[i] is in the wrong font. s

Needs to be: bus_stops[i]

(The above correction has been made in printings after December 1997)


p14 (C. L. Tondo) line 2: BOOLEAN needs semicolon for consistency with the other typedefs

Needs to be: typedef int BOOLEAN;

(The above correction has been made in printings after December 1997)


p14 (p. Sevinc) line 3: typedef char *c_string; is in inconsistent with general use of * next to type, not next to variable name

Needs to be: typedef char* c_string;


p16-17 (C. L. Tondo) line 7-11: Use of LMPin and LMPinc is inconsistent.

Needs to be:

namespace LMPinc {
   int  n;
   namespace LMPdolls {              //inner namespace
      int  sq(){ return n * n; }     //LMPinc::n
      void  pr_my_logo();
   }
   void  LMPdolls::pr_my_logo()
      { cout << "Dolls by Laura" << endl; }
}

(The above correction has been made in printings after December 1997)


p20 (Pohl) line 6: Constant definitions and inline definitions at file scope are local to that file; in other words, they are implicitly static.

Explanation: The linkage on inline has been changing. Here is what Steve Clamage of the ANSI committee stated in an email:

"The ARM said inline functions had static linkage, but didn't say what the linkage of inline class member functions was. For some time now, the draft standard has said that declaring a function inline does not affect its linkage, and that functions have external linkage unless declared static. If a function has external linkage, there is only one copy in the entire program of any of its local static objects. Existing books and compilers may have been written to earlier versions of the draft, and thus might not correspond to the current version. This aspect of inline functions is not going to change, given the schedule for publishing a final standard."

This change I believe affects inline explanation in most books. Proviso, this change may not yet have been implemented - so check your compiler. Better yet avoid situations where this can be a factor.

(No correction to the text needed.)


p33 (C. L. Tondo) line (in table): There should be more space between the exclamation point and tilde.

Needs to be: ! ~ &

(The above correction has been made in printings after December 1997)


p37 (C. L. Tondo) line (in table): int not needed before b.

Needs to be: int a = -5, b = 3, c = 0;

(The above correction has been made in printings after December 1997)


p38 (Belotsky) table entry: q = i;

Needs to be: *q = i;

(The above correction has been made in printings after December 1997)


p38 (Tondo) table entry: q = (double *)p;

Needs to be: q = (p);

(The above correction has been made in printings after December 1997)


p40 (Hill) Table comment is confusing

Needs to be: *p = 7; *p is lvalue of a, so a is assigned 7

(The above correction has been made in printings after December 1997)


p41 (Anon) Discussion of how new fails represents current compilers.

Explanation: The ANSI standard calls for new to throw the bad_alloc exception to indicate failure. The Borland 5.0 compiler throws xalloc. Many systems still do not throw exceptions, but instead return the null pointer value. Even where a system has migrated to the exception throwing behavior the programmer can use set_new_handler(0) to retain the older non-exception null pointer style.

(No correction needed to the text.)


p42 (Tondo) table entries: The table at the top of the page has incorrect descriptions of what is being deleted.

Needs to be: The three lines on the right hand side of the table:

deletes the object pointed at by ptr

deletes the object pointed at by p[i]

deletes a vector of objects pointed at by p

(The above correction has been made in printings after December 1997)


p48 (C. L. Tondo) line (in table): Unneeded semicolon after switch termination

Needs to be:

 default: ++j;
}

(The above correction has been made in printings after December 1997)


p48 (p. Sevinc) line 14: declarations allowd in first the component

Needs to be: declarations allowd in the first component


p50 (Belotsky) Inappropriate behavior for values greater than or equal to 212.

Needs to be:

if (temperature >= 212)
   cout << "Above Boiling!\n";
else if (temperature >= 32)
   cout << "Above Freezing!\n";
else
   cout << "Boy it's cold " << temperature << endl;

(The above correction has been made in printings after December 1997)


p52 (Belotsky) Factorial only works for positive integers.

Explanation: Yes the fragment assumes n >= 1), could have used documentation or assertion.

(No correction to the text needed.)


p61 (Belotsky) Wrong identation of closing brace in code.

Needs to be:

//stats finds a data sets average, max and min.
double stats(const double data[],   //data input
             int size,
             double& max,           //maximum element found
             double& min)           //minimum element
{
   double sum = max = min = data[0];

   for (int i = 1; i < size; ++i) {
      sum += data[i];
      if (data[i] > max)
         max = data[i];
      else if (data[i] < min)
         min = data[i];
   }
   return sum/size;
}

(The above correction has been made in printings after December 1997)


p64 (Belotsky) pow() works for k >= 2. It doesn't work for numbers less than 2. There should be an assertion to make sure number is 2 or more. Needs to be:
assert (k > 1);                   //k must be at least 2
if (k == 2)

(The above correction has been made in printings after December 1997)


p71 (Tondo) line -1: Friend functions also have access to private data. Change the sentence "This makes them accessible solely to member functions of the same class" to include friend functions.

Needs to be: This makes them accessible solely to member and friend functions of the same class.

(The above correction has been made in printings after December 1997)


p. 76 (Jeffery Peden) line 6: Expand bullet to include that "a class with dynamically allocated memory should also have both a default constructor and a desctructor explicitly defined."

Explanation: This is an excellent expansion on the prescriptions. Because this would affect pagination, we are unable to add it to the text unless a major revision is done.

(No correction to the text is needed.)


p. 78 (Jeffery Peden) The complex example with operator overloading has the signature friend complex operator+(complex); If the intention is to use binary operator overloading, it needs to have two arguments.

Needs to be: friend complex operator+(complex, complex);

(The above correction has been made in printings after December 1997)


p79 (Jason Christensen) line -4: It is the style of the book not to parenthesize simple arguments such as *this

Needs to be: { this -> tick(); return *this; }

(The above correction has been made in printings after December 1997)


p81 (C. L. Tondo) line 9: Function missing semicolon

Needs to be: friend ostream& operator <<(ostream&, const vect&);

(The above correction has been made in printings after December 1997)


p. 81 (Paul Sevinc) line 5: return (*this)

Needs to be: return *this

Explanation: It is the style of this book to not use parentheses with a simple return argument.

(No correction to the text is needed.)

p84 (Paul Sevinc)

salary has no constructor. The following line should be added immediately after the public declaraion:

salary(const int b) {b_sal = b; your_bonus = 0; }

p. 86 (Paul Sevinc) line 10: person(const char*; int; unsigned long); uses semicolons where commas should be

Needs to be: person(const char*, int, unsigned long);


p. 86 (Paul Ezust)

On P.86, in your example mutable.cpp, the function person::bday() must be declared const in order for the compiler to permit it to be called via the const object ira.

With or without mutable, a const object can only invoke const member functions.

If you change it to:

void bday() const { ++age;}

The program compiles and the mutability point is made.

Needs to be:

The indicated change corrects the problem. The following code is a small variation on the book that incorporates the correction.

#include <  iostream  >
#include <  string  >
using  namespace std;

class person {
public:
  person(const string n, int a, const unsigned long ss)
      :name(n), age(a), soc_sec(ss){}
  void bday() const  {++age;}
  void print() const
  { 
     cout << name << " is  " << age 
     << "  years old with SSN  " << soc_sec << endl;
  }
private:
  const string name;
  mutable int age;
  const unsigned long soc_sec;
};

int main()
{
   const person ira("ira pohl", 38, 1110111UL);
   ira.print();
   ira.bday();
   ira.print();

}

p87 (Belotsky) Wrong comment //default constructor.

Needs to be:

class my_string {
public:
   my_string() : len(0) //default constructor
      { s = new char[1];assert(s != 0); s[0] = 0; }
   explicit my_string(int n);        //disallow conversion
   my_string(const my_string& str);  //copy constructor
   my_string(const char* p);         //conversion constructor
   ~my_string() { delete []s; }
   my_string& operator=(const my_string& str);
   my_string operator+(const my_string& str);
   friend ostream& 
      operator<<(ostream& out, const my_string& str);
   void concat(const my_string& a, const my_string& b);
private:
   char* s;
   int   len;
};

my_string::my_string(const int n)
{
   s = new char[n + 1];
   assert (s != 0);
   s[0] = 0;
   len = n;
}
(The above correction has been made in printings after December 1997)
p88 (Jason Christensen) line -7: It is the style of the book not to parenthesize simple arguments such as *this

Needs to be: return *this;

(The above correction has been made in printings after December 1997)


p. 89 (Paul Sevinc) line -12: variable name tr is incorrect

Needs to be: char * str = ...


p92 (C. L. Tondo) line 17-18: In keeping with general style of using const for arguments which won't be changed, the constructors should use const

Needs to be:

 vect_bnd(const vect_bnd& v);      //copy constructor
 vect_bnd(const vect& v);          //conversion constructor
.....

//conversion constructor
vect_bnd::vect_bnd(const vect& v) :
          vect(v), l_bnd(0), u_bnd(size - 1) { }

//copy constructor
vect_bnd::vect_bnd(const vect_bnd& v) :
          vect(v), 

(The above correction has been made in printings after December 1997)


p92 (Jason Christensen) line 21-22: It is the style of the book not to parenthesize simple arguments such as u_bnd

Needs to be:

   int ub() const { return u_bnd; }
   int lb() const { return l_bnd; }
(The above correction has been made in printings after December 1997)
p. 95 (Jeffrey Peden) line -2 - -6: Base* and Derived should be switched.

Needs to be: class Base { .....}; class Derived:Base { ..... }; void fcn(Base* ptr) { Derived* bptr = dynamic_cast = < Derived* >(ptr); In this example, the case converts the pointer value ptr to a Derived*.

(The above correction has been made in printings after December 1997)


p101 (Belotsky) Wrong code on 4th line cout << endl << stu.name << ", "

Needs to be: out << endl << stu.name << ", " The ostream argument out is clearly intended here.

(The above correction has been made in printings after December 1997)


p107 (Belotsky) Wrong style in that friend is listed in private.

Needs to be:

template < class T >

class matrix
    { public: friend void foo_bar();
   
//universal friend vect< T >product(vect< T > v); //instantiated ····· };

Explanation: By convention friends are stylistically considered part of the public interface of the class. However there is no programming or semantic distinction when friend function are listed in non-public access of a class.

(The above correction has been made in printings after December 1997)


p109-111 (Belotsky) This code is confused e.g. class vect_iterator is never used,is V.size in operator=, operator+ is written inappropriately. main() uses vector instead of vect. Improvements are suggested which we incorporate.

Needs to be:

//templates for vect with associated iterator class
#include  < iostream.h >
#include  < assert.h >      //for assert
< class T > 
class  vect_iterator;
template < class T >vect {
public:
   //constructors and destructor
   typedef T* iterator;
   explicit vect(int n = 10);  //default constructor
   vect(const vect& v);        //copy constructor
   vect(const T a[], int n);   //from array
   ~vect() { delete [] p; }
   iterator begin(){ return p;}
   iterator end(){ return p + size;}
   T&  operator[](int i) const;
   vect& operator=(const vect& v);
   friend vect
      operator+(const vect& v1,               const vect& v2);
   friend ostream&
      operator<<(ostream& out,
                 const vect& v);
   friend class vect_iterator< T >;
private:
   T*    p;     //base pointer
   int   size;  //number of elements
};

//default constructor
template < class T >
vect < T >::vect(int n): size(n)
{  assert(n > 0); 
   p = new T[size];
   assert(p != 0);
}  

//copy constructor
template< class T >
vect < T >::vect(const vect< T >& v)
{
   size = v.size;
   p = new T[size];
   assert (p != 0);
   for (int i = 0; i < size; ++i)
      p[i] = v.p[i];
}

//Initializing vect from an array
template< class T >
vect< T >::vect(const T a[], int n) : size (n)
{
   assert (n > 0);
   p = new T[size];
   assert (p != 0);
   for (int i = 0; i < size; ++i)
      p[i] = a[i];
}

//overloaded subscript operator
template< class T >
T& vect< T >::operator[](int i) const
{
   assert (i >= 0 && i < size);
   return p[i];
}   

//overloaded output operator template< class T >
ostream& operator<<(ostream& out,
                    const vect< T >& v)
{
   for (int i = 0; i <= (v.size-1); ++i)
      out << v.p[i] << '\t';
   return (out << endl);
}

template< class T >
vect< T >& vect< T >::operator=(const vect< T >& v)
{
   assert(v.size == size);
   for (int i = 0; i < size; ++i)
      p[i] = v.p[i];
   return *this;
}

template< class T >
vect< T > operator+(const vect< T >& v1, const vect< T >& v2)
{
   assert(v1.size == v2.size) ;
   vect< T >  sum(v1.size);
   for (int i = 0; i < v1.size; ++i)
      sum.p[i] = v1.p[i] + v2.p[i];
   return sum;
}

template< class T >
void init_vect(vect< T >& v, T start, T incr)
{
   for (vect< T >::iterator p = v.begin(); p != v.end(); ++p)
   {      
      *p = start;
      start += incr; //operator+= defined for T
   }
}

int main()
{
   vect < double > v(5), t(5);
   vect < double >::iterator p ;
   init_vect(v, 1.5, 1.0); 
   cout << "initial vect values\n"; 
   for (p = v.begin() ; p != v.end(); ++p)
      cout << *p << " , ";
   cout << endl;
   t = v;       //test assignment
   v = v + t;   //test addition
   cout << "\n After doubling the values backward are\n"; 
   p = v.end();
   do {     --p;
      cout << *p << " , ";
   } while (p != v.begin());
}

Explanation:  In template code what is not generated may not 
fail syntactically. In printing 1, the existing code did not test
 the incorrect assignment and addition code templates. 
Also for some reason in main(), vect< double > 
got mutated into vector < double >. 
I apologize for these multiple errors in the code.

(The above correction has been made in printings after December 1997) 

p119 (Jason Christensen) line -8: It is the style of the book not to parenthesize simple arguments such as p[i]

Needs to be: return p[i];

(The above correction has been made in printings after December 1997)


p120 (Jason Christensen) line 13: It is the style of the book not to parenthesize simple arguments such as *this

Needs to be: return *this;

(The above correction has been made in printings after December 1997)


p123 (Galen Tackett) There are a considerable number of missing functions such as ios::setf() and ios::unsetf().

Explanation: Yes, this section needs to be beefed up. The Teale (see p190) IOS93 is exhaustive, but somewhat out of date.

(No correction to the text will be made since it would cause repagination.) In later editions this might be modified.


p127 (Author) The code 6 lines from bottom s = suit(n/13);.

Needs to be: static_cast < suit >(n / 13);

Explanation: Old style casts are very poor style and considered obsolete.

(The above correction has been made in printings after December 1997)


p133 (Belotsky) In the second paragraph "<<" is called the get from operator.

Needs to be: The overloaded >> get from operator ...

(The above correction has been made in printings after December 1997)


p135 (C. L. Tondo) line -8: Semicolon missing after function

Needs to be: int good():

(The above correction has been made in printings after December 1997)


p135 (C. L. Tondo) line -1: Missing semicolon, parenthesis and const from void

Needs to be: operator void*() const;

(The above correction has been made in printings after December 1997)


p138 (Belotsky) Bottom of the page is confusing.

Explanation: Both stdio and iostream should be synchronized if both are working with the same streams. Otherwise, mixing the two forms of IO should not cause a problem.

(No correction to the text needs to be made.)


p. 156 (Paul Sevinc) line 3: Class (uppercase incorrect)

Needs to be: class

(The above correction has been made in printings after December 1997)


p. 160 and 161 (Paul Sevinc) multiple lines: Class (uppercase incorrect)

Needs to be: class

(The above correction has been made in printings after December 1997)


p163 (Belotsky) The third listed function is void BidiIter(...

Needs to be: void reverse(... (The above correction has been made in printings after December 1997)


p169 (Paul Sevinc) line 8

"less" should be "lesser" in the table


p179 (Belotsky) mid page the comment //s1"I 7 years old am" has wrong spacing.

Needs to be: s1.insert(2, s2); // s1 " I 7 years old am "

(The above correction has been made in printings after December 1997)


p177 - 181 (Peden) The string library has been modified and the new modifications are not properly reflected in the tables. Multiple changes are needed to bring string into compliance with the new standard. A new example showing the STL string constructors has also been developed.

The changes are listed below:

p177 line 2: seven constructors

Needs to be: six constructors

p177 line 3-4: Two conversions were removed from the standard. Delete sentence "Two of these ..."

p177 String Constructor Members table entries 3 and 5: Two conversions were removed from the standard. Delete

string(const vector...)
string(size_t size, ...)

p177 String Constructor Members table: One conversion was added to the standard. Insert in place of string(const vector...) string(InputIterator b, InputIterator e) constructor from the InputInterator range b to e

p177 Last Item in String Constructor Members table has order of arguments reversed. string(char c, size_t n = 1) is incorrect and cannot have the default argument. Needs to be: string(size_t n, char c)

p178 Third table entry from bottom of String overloaded Operator Members, operator vector< ... should be removed

p178 line -3 order of arguments reversed. append(char c, size_t n = 1) is incorrect and cannot have the default argument.

Needs to be: append(size_t n, char c)

p179 line 8 has order of arguments reversed. assign(char c, size_t n = 1) is incorrect and cannot have the default argument.

Needs to be: assign(size_t n, char c)

p179 line -5 has order of arguments reversed. insert(char c, size_t n = 1) is incorrect and cannot have the default argument.

Needs to be: insert(size_t n, char c)

p179 line 8 - needs another assign at end of assigns list

Needs to be: string& assign(InputIterator b, InputIterator e);

p179 line -4 needs 3 more inserts at end of inserts list

Needs to be:

iterator insert(iterator p, char c);
iterator insert(iterator p, size_t n, char c);
void insert(iterator p, InputIterator b, InputIterator e);

p180 Second table entry in String Members table has string& replace(pos, n, c, rep = 1); The rep argument has been removed.

Needs to be: string& rplace(pos, n, c); and the comment "repeated rep times" needs to be removed.

p180 Third table entry from bottom in String Members table has comment returns the private member res; the first function resets this which needs to be modified.

Needs to be: allocates memory for string; returns the size of the allocation

p180 Third and fourth table entries in String Members table and their explanations should be removed. The two items for removal are: char get_at(pos) const; and void put_at(pos, c);

p181 line 3 has int compare (const char* p, size_t pos) const which needs a default value on last argument.

Needs to be: int compare (const char* p, size_t pos = 0) const

p181 line 3 has int compare (char c, size_t pos, size_t rep = 1) const; which must be removed altogether.

(The above correction has been made in printings after December 1997)