Errata for 7th and 8th printings of The C++ Programming Language

Errata for Bjarne Stroustrup: The C++ Programming Language (3rd edition), Addison-Wesley, 1997. ISBN0-201-88954-4. Errata for the 7th and 8th printings yielding the 9th.

Errors and Clarifications

Preface:

Chapter 1:

Chapter 2:

pg 41 add sizes to the stack definitions:

Stack< char> sc(200);		// stack of 200 characters
Stack< complex> scplx(30);	// stack of 30 complex numbers
Stack< list< int> > sli(45);	// stack of 45 lists of integers
Chapter 3:

pg 54 a slightly improved version of print_entry():

void print_entry(const string& s)
{
	typedef list< Entry>::const_iterator LI;

	for (LI i = phone_book.begin(); i != phone_book.end(); ++i) {
		Entry& e = *i;	// reference used as shorthand
		if (s == e.name) {
			cout << e.name << ' ' << e.number << '\n';
			return;
		}
	}
}

Chapter 4:

Chapter 5:

Chapter 6:

pg 130: the 3rd paragraph of 6.2.7 can be clarified like this: "The static_cast operator converts between related types such as one pointer type to another in the same class hierarchy, an enumeration to an integral type, or a floating-point type to an integral type. The reinterpret_cast handles conversions between unrelated types such as an integer to a pointer or a pointer to an unrelated pointer type."

Chapter 7:

pg 146 s/but not as a non-const argument/but not as a non-const& argument/

Chapter 8:

pg 190 s/Token_value Lexer::get_token()/Lexer::Token_value Lexer::get_token()/

pg 192 s/input->get(ch);// immediately before "return;"

Chapter 9:

Chapter 10:

Chapter 11:

pg 266 replace the last paragraph with:

Consider a binary operator @. If x is of type X and y is of type Y, x@y is resolved like this:

Declarations for several operatoras may be found and overload resolution rules (7.4) are used to find the best match, if any.

pg 280 replace the last example by:

// no f() in this scope

class X {
	friend void f();		// useless
	friend void h(const X&);	// can be found through its argument
};

void g(const X& x)
{
	f();	// no f() in scope
	h(x);	// X's friend h()
}	

pg 296 s/operator char()/operator char() const/

Chapter 12:

pg 307 As the last paragraph of 12.2.3 add: "Note that if you don't define a copy assignment operator, the compiler will generate one (11.7). This implies that assignment operators are not inherited."

pg 311 s/print_list(set/print_list(const list/ twice

pg 311 s/for(set/for(list/

pg 312 set/list/ in main()

Chapter 13:

pg 330 s/p = new/rep = new/ twice

pg 335 s/ T lookup(/T& lookup(/

pg 335 s/ int f(/Record& f(/

pg 338 s/get_nth(v/get_nth< int>(v/ thrice

pg 346: a more complete and correct version of the Basic_ops example:

template < class C> class Basic_ops {	// basic operators on containers
public:
	bool operator==(const C&) const;	// compare all elements
	bool operator!=(const C&) const;
	// ...
	const C& derived() { return static_cast< const C&>(*this); } // give access to container operations

};

template< class T> class Math_container : public Basic_ops< Math_container< T> > {
public:
	size_t size() const;
	T& operator[](size_t);
	const T& operator[](size_t) const;
	// ...
};

template < class C> bool Basic_ops< C>::operator==(const C& a) const
{
	if (derived().size() != a.size()) return false;
	for (int i = 0; i< derived().size(); ++i)
		if (derived()[i] != a[i]) return false;
	return true;
}

pg 349 s/g(set< Circle>& s)/g(set< Circle*>& s)/

Chapter 14:

pg 368 s/vector< auto_ptr< Shape*> >& v;/vector< auto_ptr< Shape> >& v;/

pg 372 s/Vector::Vector(int sz)/Vector(int sz)/

pg 379 s/: Yerr {/: public Yerr {/

Chapter 15:

pg 399 s/12.3/12.4.3/

pg 400 s/and BB_popup_slider./and BB_popup_ival_slider./

pg 401 s/set_color(Color/void set_color(Color/ twice

pg 414 correct the throw-specifications:

   const type_info& typeid(type_name) throw();
   const type_info& typeid(expression) throw(bad_typeid);

PG 426 /ten consecutive keywords/ten different consecutive keywords/

Chapter 16:

Chapter 17:

pg 455 Replace the first paragraph by: "The most tempting alternative, &c[7] , actually works with the obvious implementation of vector, where c[7] refers to an element and its address is a valid iterator. However, c might be a container where the iterator isn't a simple pointer to an element. For example, map 's subscripting operator (17.4.1.3) returns a mapped_type& rather than a reference to an element (a value_type&).

Not all containers support + for their iterators. For example, a list does not support even c.begin()+7. If you really want to add 7 to a list::iterator, you'll have to use ++ repeatedly."

pg 463 s/Most containers/Vectors and deques/

pg 467: before "return toupper" add "if (q == y.end()) return false;"

pg 477 s/(see sec14.4.7)/(see sec14.4.1)/

pg 479 s/(see sec14.4.7)/(see sec14.4.1)/

pg 485 s/bool operator()(const T& x, const T& y) const/bool operator()(const value_type& x, const value_type& y) const/

pg 488 s/phone_book.erase/m.erase/

Chapter 18:

pg 516 Here is a less confusing variant of the 3rd paragraph:

Instead of finding the first element not less than its corresponding element in the other sequence, we might like to find the first element less than its corresponding element. We can do this by looking for the first pair that fails the complementary predicate greater_equal:

	p1 = mismatch(vi.begin(),vi.end(),li.begin(),greater_equal< int>());
Alternatively, we could present the sequences in the opposite order and use less_equal:
	Pair< LI,VI> p2 = mismatch(li.begin(),li.end(),vi.begin(),less_equal< int>());

pg 520 s/lsp)/c)/

pg 527 s/equal_to< In::value_type,In2::value_type>()/equal_to< In::value_type>()/

pg 539 last example:

class Compare_copies_sold {
public:
	int operator()(const Book& b1, const Book& b2) const
		{ return b1.copies_sold()>b2.copies_sold(); }	// sort in decreasing order
};
pg 540 first example:
void f(const vector< Book>& sales)	// find the top ten books
{
	vector< Book> bestsellers(10);
	partial_sort_copy(sales.begin(),sales.end(),
			bestsellers.begin(),bestsellers.end(),Compare_copies_sold());
	copy(bestsellers.begin(),bestsellers.end(),ostream_iterator< Book>(cout,"\n"));
}

pg 544 s/cmp(b,a)/cmp(a,b)/

Chapter 19:

pg 557: replace f():

void f(vector< int>& v, list< char>& lst)
{
	v.rbegin()[3] = 7;		// ok: random-access iterator
	lst.rbegin()[3] = '4';		// error: bidirectional iterator doesn't support []
	*(++++++lst.rbegin()) = '4'; 	// ok!
}

pg 560 s/basic_istreambuf/basic_streambuf/ twice

pg 563,564 make valid(), operator*(), operator->(), operator+(), operator[](), index(), and unchecked() const member functions.

pg 572 the correct declarations of v and m are:

vector< int,Pool_alloc< int> > v;
map< string,number,Pool_alloc< pair< const string,number> > > m;

pg 575 fix the type of the returned values of raw_storage_iterator like this:

raw_storage_iterator& operator*() { return *this; }

raw_storage_iterator& operator=(const T& val)
{
	T* pp = &*p;
	new(pp) T(val);
	return *this;
}

raw_storage_iterator& operator++()
{
       ++p;
       return *this;
}

raw_storage_iterator operator++(int)
{
	raw_storage_iterator tmp = *this;
	p++;
	return tmp;
}
Chapter 20:

pg 583 Add to the last paragraph: The ``character type'' Ch must behave like a character. In particular, it may not have a user-specified copy constructor, destructor, or copy assignment.

Chapter 21:

pg 641 replace the compose2() example with: An initial value for a string stream is treated analogously to the way a file stream treats its file:

string compose2(int n, const string& cs)	// equivalent to compose()
{
	ostringstream ost("error(",ios_base::ate); // start writing at end
	ost << n << ") " << std_message[n] << " (user comment: " << cs << ')';
	return ost.str();
}

(recent standards clarification)

pg 647 add after the rdbuf() example: "Note that on some systems, it can be hard to determine if input is available. Thus, in_avail() might be (poorly) implemented to return 0 in cases where an input operation would succeed."

Chapter 22:

pg 667: a better grow2():

void grow2(valarray< int>& v, size_t n)
{
	if (n<=v.size()) return;

	valarray< int> tmp = v;
	slice s(0,v.size(),1);	// subarray of v.size() elements (see 22.4.5)

	v.resize(n);			// resizing doesn't preserve element values
	v[s] = tmp;			// copy elements back into the first part of v
}

pg 672 s/Matrix& Matrix(const Matrix&);/Matrix(const Matrix&);/

pg 686 Randint assumes that ints are at least 32 bits. To get a version that works even if an int is 16 bits, replace all 'int's by 'long's.

Chapter 23:

Chapter 24:

Appendix A:

Appendix B:

pg 824 add Key parameter to map:

template< class Key, class T, class LT = less< T> > class map {
	// ...
};

map< string,int> m;			// Oops: default template arguments not implemented
map< string,int,less< string> > m2;	// workaround: be explicit

Appendix C:


Typos

Preface:

Chapter 1:

Chapter 2:

Chapter 3:

Chapter 4:

Chapter 5:

Chapter 6:

Chapter 7:

Chapter 8:

pg 194 s/namespaces names/namespace names/

Chapter 9:

pg 203 s/, while a/ and/

Chapter 10:

Chapter 11:

pg 271 s/initialize x by (2,0)/initialize y by (2,0)/

pg 296 s/int c/char c/ twice

Chapter 12:

pg 303 s/(name, age, etc.)/(first_name, department, etc.)/

pg 312 s/Employee::print_list()/print_list()/

pg 316 s/flashing_ival_slider/Flashing_ival_slider/

pg 316 s/popup_ival_slider/Popup_ival_slider/

pg 319 s/inherited by Ival_box/inherited from Ival_box/

Chapter 13:

pg 332 s/an member/a member/

pg 334 s/Vol. l3/Vol. 3/

pg 345 s/list/List/ (twice)

pg 346 s/3.7.1/3.7.2/

Chapter 14:

Chapter 15:

pg 405 s/3.7.1/3.7.2/

pg 405 s/list/List/ twice

pg 407 s/publically/publicly/

pg 410 s/My_box/My_slider/ (twice in diagram)

Chapter 16:

pg 436 s/vector/Vector/

pg 436 s/list/List/

pg 446 s/3.7.1/3.7.2/

Chapter 17:

pg 469 s/3.7.1/3.7.2/

pg 484 s/described by a pair input iterator In./described by a pair of input iterators./

pg 488 s/the key k./val's key (val.first)./

Chapter 18:

Chapter 19:

Chapter 20:

Chapter 21:

Chapter 22:

Chapter 23:

Chapter 24:

Chapter 25:

Appendix A:

pg 806 s/valiable/variable/

Appendix B:

Appendix C:

pg 853 s/char*/const char*/ thrice to avoid deprecated conversion

pg 856 s/or T is char?/or T is const char?/