《C++ 程式語言經典本》勘誤

最新修訂日期:


寫在前面

本頁是《C++ 程式語言經典本》的勘誤。

這份勘誤,一部份是由於原著 The C++ Programming Language, 3rd Edition 本身即有的錯誤,一部份是譯者在翻譯過程中所引入的錯誤。

嚴格來說,原作者 Bjarne Stroustrup 在他的網頁裡為本書所列的 勘誤表, 並不全然是「勘」,有些反而是「補充」。 這一點要特別注意。

如果您發現中譯本有任何可能的錯誤,請與我連絡, 我會盡快確認並加在勘誤表上。


勘誤表

變動歷程紀錄

7/24
1-101-216-236-3210-2211-3611-4712-2213-915-3515-4417-3717-4318-918-1718-4018-5019-419-2219-2219-2919-3021-1621-4121-5421-5521-5822-23B-16C-4C-7C-11C-54 頁。
7/14
9-410-3210-3212-623-1 頁。
6/27
7-17 頁。
6/24
6-22 頁。
6/17
10-1411-3112-1815-715-1215-13 頁。
之前
已不可考…… :) 請見其他未特別註明者。

勘誤內容

1-10 頁, 第二段文字,原著補充
C 可算是 C++ 的子集要不是為了補上 C 型別系統的漏洞(請參考附錄B),大體而言, C 可算是 C++ 的子集
1-21 頁, 倒數第四段,原著筆誤
Eric Gamma → Erich
2-24 頁, 第一段文字,譯本筆誤
跟 §2.5.4 裡的 Shape 抽象型別一樣 → Stack
3-21 頁, 中間一大塊程式碼,原著更正
return !is.eof() &&||
4-14 頁, 倒數第二大塊程式碼,譯本筆誤
原程式碼 新程式碼
int count;
int count; // 錯誤:重複定義

extern int error_number;
extern short error_number; // 錯誤:型別不符
extern int error_number;
extern int error_number;
5-9 頁, 中間一塊程式輸出,譯本筆誤
0x7fffaedc 0x7fffaefed
6-22 頁, §6.2.2 倒數第二段,譯本筆誤
f1 函數呼叫用了兩個參數: v[ii]i++i
6-23 頁, 倒數第一段,原著補充
6-32 頁, 倒數第一段,原著更正
都可能產生未經定義的結果 → 由實作環境決定的、不具可攜性的
7-17 頁, 中間一塊程式碼的註解文字(出現兩次),譯本補充
arg不定參數列資訊
8-21 頁,最上方程式碼,原著更正
原程式碼
void My_lib::my_fct(My_lib::Vector<My_lib::String>& v) // OK
新程式碼
void My_lib::my_fct(String& v) // OK;此處的 String 即指 My_lib::String,亦即 His_string::String
9-4 頁, 第二大段文字,譯本誤譯
編譯器製作者喜歡看到的是像底下這種(完全合乎邏輯的) 外部連結性與內嵌函數的組合因此,為了讓編譯器製作者好過一些,C++ 禁止底下這種 外部連結性與內嵌函數的組合用法(儘管它完全合乎邏輯)
9-13 頁,第二大段程式碼,譯本筆誤
原程式碼 新程式碼
extern "C" int f();

int g()
{
    return f(1);   // 錯:不應有參數
}
extern "C" {
    char* strcpy(char*, const char*);
    int strcmp(const char*, const char*);
    int strlen(const char*);
    //...
}
9-30 頁,§9.4.1.1 的倒數第二段,原著補充
如果某物件在 atexit(f) 執行之前就已建構出來了凡是在 atexit(f) 執行之前就已被建構完成的靜態物件 (全域物件、函數內之 static 物件、類別內之 static 物件)
10-14 頁, 倒數第一段文字,譯本筆誤
如說,除了名字不同之外 →
10-22 頁, 第一大塊程式碼、以及中間兩行正文,譯本筆誤
重複出現,請逕行刪去。
10-32 頁, 中間第一大塊程式碼,譯本筆誤
(const string& n, Date fd);)
10-32 頁, 倒數第三段文字,譯本筆誤
成員初始化串列的前面是分號冒號
11-15 頁,倒數第二段,原著補充
顯式或隱式利用建構式建立起來的物件是自動型物件 → 在運算式內被顯式或隱式利用建構式建立起來的物件是自動型物件
11-31 頁, §11.7.1 的第一大段第二小塊文字,譯本筆誤
有人就 9 會寫成有人就會寫成
11-36 頁, 第一塊程式碼,原著筆誤
Iter for_eachFct
return b;f
11-47 頁, 第 1 題,原著筆誤
operator+(int);X operator
operator+(X);Y operator
12-6 頁, 第一大塊程式碼,譯本排版問題
「然而,衍生類別無法使用基底類別私有區內的名字:」這一行, 應該是屬於普通內文,而非程式碼的一部份; 應該印成新細明體,而非楷體。
12-18 頁, 程式碼最後面,譯本漏行
請加上這樣的一行: virtual void prompt() {}
12-22 頁, 第一段,原著補充
最好將資料保持在私有狀態 → 資料成員
13-9 頁, 第一段文字,原著筆誤
都不能以整數 7 來初始化指標 T*Link*
14-2 頁, 倒數第一段,譯本筆誤
C++ 預設做法居是結束程式 →
15-7 頁, 倒數第二段,譯本筆誤
(§14.2.4) → 15
15-12 頁, 中間一塊程式碼,譯本筆誤
// 顯示時鐘的臉與手鐘面與指針
15-13 頁, 第一大塊程式碼,譯本筆誤
// 顯示時鐘的臉與手鐘面與指針
15-35 頁, 程式碼,原著補充
hash_map<type_info*const type_info*
15-44 頁, §15.6.1 第一塊程式碼,原著筆誤
void operator delete[](void*, size_t);(void*)
17-29 頁, 中間的程式碼,原著補充
原程式碼
return pair<int,double>(c,i);  // 需要做轉型
新程式碼
pair<char,int> x(c,i);
//...
return x; // 需要做 pair<char,int> → pair<int,double> 的轉型動作
17-37 頁, 最後一段,原著補充
刪除 end() 是無害的 (譯註:就像「delete 0;」指令一樣是無害的)如果 em.end() 的話, 呼叫 m.erase(b,e) 是無害的 (假設此處的 b 真的有指向 m 的某個元素,或者等於 m.end())。 然而,若 pm.end() 的話, 那麼,呼叫 m.erase(p) 便是個嚴重錯誤,可能會破壞容器。
17-43 頁, §17.5.3 最後一段,原著筆誤
pow(i, 2)2, i
17-53 頁, 中間的程式碼,原著更正
mapped_type& hash_map::hash_map<Key,T,H,EQ,A>
17-53 頁,中間的程式碼,原著更正
b.size()*max_loadsize_type(b.size()*max_load)
17-54 頁,倒數第二行的程式碼,原著更正
void hash_map::hash_map<Key,T,H,EQ,A>
17-55 頁,最上方的程式碼,原著更正
b.clear();fill(b.begin(), b.end(), (Entry*) 0);
17-55 頁,§17.6.2.2 的最後一段程式碼,原著更正
void hash_map::hash_map<Key,T,H,EQ,A>
17-56 頁,倒數第二大段的程式碼,原著補充
原程式碼
size_t Hash<char*>::operator()(const char* key) const
{
  size_t res = 0;

  while (*key) res = (res<<1)^*key++; // 使用字元的整數值
  return res;
}
新程式碼
typedef char* Pchar;
template<> size_t Hash<Pchar>::operator()(const Pchar& key) const
{
  size_t res = 0;
  const char* p = key;
  while (*p) res = (res<<1)^*p++; // 使用字元的整數值
  return res;
}
18-9 頁, 倒數第二塊程式碼(出現兩次),原著筆誤
iterator_typeiterator
18-17 頁, 第二大塊程式碼,譯本筆誤
請整個更正為:
void f(list<int>& c)
{
    list<int>::const_iterator p = find_if(c.begin(), c.end(), less_than<int>(7));
    //...
}
18-40 頁, 第一塊程式碼,原著筆誤
generate(v2, &v2[900], Randint)Randint()
18-50 頁, §18.9 最後一塊程式碼的倒數第二行,原著筆誤
NocaseNocase()
19-4 頁, §19.2.1 最後一段程式碼,原著筆誤
In i,In&
19-19 頁, 最後兩個函數,原著更正
c->begin() - currcurr - c->begin()
19-22 頁, 第一塊程式碼(出現五次),原著補充
將「typename C::」刪去。
19-22 頁, 中間一塊程式碼,原著筆誤
copy(vec.begin(), vec.end(), lst.begin(), lst.end());begin()
19-26 頁, 第一段文字,原著更正
對所有標準配置者來說,它就是 const void*。 → void*
19-29 頁, 程式碼,原著補充
原程式碼
struct Chunk {
    enum { size = 8*1024-16 };
    Chunk* next;
    char mem[size];
};
新程式碼
struct Chunk {
    enum { size = 8*1024-16 }; // 略小於 8K,好讓整個 Chunk 能塞入 8K 空間
    char mem[size];            // 先配置空間,以嚴格對齊邊界
    Chunk* next;
};
19-30 頁, 第一段文字,原著筆誤
(如 rebind() 所要求的) → rebind
21-16 頁, 第一段文字,原著補充
試圖對一個不是處於 good() 狀態的串流 施以任何輸入動作都是無效的,(對該輸入變數而言)都是無效的
21-28 頁, 第一段的程式碼,原著更正
原程式碼
fmtflags setf(fmtflags f, fmtflags mask)  // 增設旗標
   { return flags(flags() | (f & mask)); }
新程式碼
fmtflags setf(fmtflags f, fmtflags mask)  // 根據遮罩來清除並設定旗標
   { return flags((flags()&~mask) | (f & mask)); }
21-41 頁, 程式碼,原著筆誤
Bound_form Form::operator()(double d) { return Bound_form) const {
21-54 頁, 第二大塊程式碼,原著筆誤
將「basic_streambuf();」這行刪去。
21-55 頁, 最後一大塊程式碼,原著筆誤
將「basic_streambuf();」這行塞入「//...」的下一行。
21-58 頁, 最後一塊程式碼,原著筆誤
std::locale::global());locale()
22-23 頁, 中間的程式碼,原著更正
double mul(const valarray<double>& v1Cslice_iter
22-23 頁, 中間的程式碼,原著筆誤
res(i) = mul[i]
23-1 頁, 第一段文字,譯本筆誤
§21.4 → 23
§21.5 → 23
B-16 頁, 第 10 條,原著筆誤
自列舉物隱式轉換成 intint 值隱式轉換成列舉物
C-4 頁, 第一個表格的第三欄,原著筆誤
將「??? ?」一項刪去。
C-7 頁, 最後一段文字以及程式碼(出現五次),原著筆誤
未定義由實作環境決定
C-11 頁, 第一段文字,原著筆誤
255127
C-54 頁, 第 5 條,原著筆誤
若所在系統缺少 { } [ ] | 字元 → { } [ ] | !
若缺少 \!\

←