圖書信息
傳世經典書叢
《Exceptional C++:47個C++工程難題、編程問題和解決方案(中文版)》
[美]Herb Sutter 著
聶雪軍 譯
ISBN 978-7-121-17085-0
2012年6月出版
定價:59.00元
16開
276頁
傳承大師智慧 領悟技術本真
經典名著 翻譯良品 典藏不二之選
譯者序
得知本書要再版,心裡很是高興。2006年翻譯完本書時,還在忐忑地等待女兒出生;而今再版,女兒都已經快5歲了,不由感嘆時光荏苒,如白駒過隙。在這5年時間裡,C++語言本身並無太大突破,或許最令人期待的就是——最新的C++程式語言國際標準(C++ 0x,或者說C++ 2011)將於今年夏天正式發布,歷時8年的C++標準修訂工作有望最終完成。新標準對並行編程、Labdam表達式以及右值引用等特性的支持,將進一步提升C++的強大功能。
本書是一本頗具分量的C++經典著作,其特點在2006年版譯序中有詳細的說明。在此次對譯稿的重新修訂過程中,完成的工作主要包括:
內容勘誤
2006年本書出版後,陸續有讀者指出書中存在一些翻譯有誤或者不到位的地方。在這次修訂過程中,我收集了讀者通過網上論壇、E-mail等提交的反饋,以及自己平時與同事交流中收到的反饋,一併對其中的錯漏之處進行了修正。
語言提煉
在收集到的意見中,有不少讀者反映翻譯的表述有些拖沓,應該更簡練一些。當年自己覺得似乎並無不妥,然而在時隔5年後,當我從旁觀者的角度再次閱讀2006年的譯稿時,發現在行文上確實有些囉嗦,讀起來頗為不順,看來真的是“當局者迷,旁觀者清”。因此,借這次修訂的機會,我對譯稿的語言重新進行組織,儘可能提高文字的簡潔性,並確保內容的精確性。在修訂完後重新統計,居然比2006年譯稿精簡了約4千字,不禁汗顏。
在重新修訂本書時,我試著把書中47個條款的問題重新解答了一遍,結果發現仍有不少問題沒有拿到滿分。而且,經歷了5年的C++編碼實踐和沉澱後,看待問題的角度和深度也與5年前大有區別,對相同問題又有了新的理解和認識,正可謂“溫故而知新”。這也是我在修訂過程中的最深體會,希望無論新讀者還是老讀者都能從本書中再次有所收穫。
本書與More Exceptional C++和Exceptional C++ Style同屬Herb Sutter撰寫的C++經典系列,讀者在閱讀本書的同時,可以與其他兩本書的內容結合起來,相互補充,舉一反三,這對進一步提高自己的C++編程能力是非常有益的。
在經過這次修訂後,譯稿的質量或有進一步提高,但其中難免還有不妥或者疏漏的地方,歡迎各位讀者隨時反饋與指正。
對本書的評價,可一言以蔽之:經典之作,歷久彌新。
聶雪軍
2011年5月於武漢
譯者原序
這是一本大師級的C++書籍。
成為一名大師,是每個C++程式設計師的夢想。在經過了幾年的實踐之後,許多程式設計師都能在日常工作中很好地套用C++來解決編程問題和實現功能模組。然而,在處理一些較為複雜的問題時,卻往往還是會感到有些力不從心。例如,我們很難編寫出非常穩定的代碼;在設計大型系統時,總會有一些不完善的地方。有時候雖然能夠從直覺上感覺到一些東西,但卻始終無法找到問題的關鍵所在,也很難確定該從哪些方面來入手。究其原因,這是因為雖然我們已經掌握了C++,但對於一些深層次的細節,還沒有進行深入和細緻的研究。對於上述這些問題,本書將會給出很好的解答。
本書主要有以下的特點:
深入性
這是一本頗具深度的書籍,本書對C++的分析深度是很多C++書籍所不能達到的。對於書中的每個主題,作者首先從理論上進行了嚴謹的論證,然後再給出實際的代碼進行全面和細緻的分析,基本上做到了詳盡無遺。對於每一種套用,作者都非常清楚地解釋了為什麼要這么做,以及這種做法的使用環境。如果你已經具備了一定的C++基礎,那么本書的內容能夠使你的C++能力產生質的提升。
拓展性
C++中的一些特性,例如異常安全性,對於編寫高質量的程式來說,是非常必要的。但遺憾的是,到目前為止,了解並使用這些特性的程式設計師還是不多的。大多數的程式設計師都還是停留在一些普通的C++特性上,而很少會去研究C++的高級特性。本書對一些C++的高級特性進行了詳細的闡述和分析,特別指出了在哪些情況下,這些特性的優勢能夠得到最大的發揮,以及這些特性能夠為我們帶來怎樣的好處。對這些高級特性的學習,不僅能夠使我們從更全面的角度來看待問題,而且也能為我們拓展新的設計思路。
糾錯性
在學習C++的過程中,我們免不了會犯一些錯誤,例如對繼承的過度使用,好像“沒有大量繼承的OO就不是OO”,而我們自己是很難發現這些錯誤的。久而久之,你會不知不覺地陷入一些思維陷阱中,並因此養成不好的編程習慣。本書的一大特點就是,在分析問題的同時,還指出了一些不好的編程習慣和常見的錯誤,並且解釋了為什麼這些做法是不好的和錯誤的。在閱讀了這部分內容之後,你肯定會發現其中有些錯誤是自己原來沒有覺察到的,並且在今後的工作中,也會有意識地去改正這些錯誤。
對於本書的翻譯工作,我投入了大量的時間和精力,工作到凌晨是常有的事情。在翻譯的過程中,對於每一個難以理解的地方,我首先保證自己充分地理解,然後再用淺顯的語言表達出來,幫助讀者更快、更準確地理解書中的內容。由於本人的時間和水平有限,4翻譯中的疏漏和錯誤在所難免,4還望讀者和同行不吝指正。
書山有路勤為徑,只有讓自己不斷地學習,不斷地提高,成為大師的夢想才有可能實現。祝願所有的C++程式設計師都能實現自己的夢想。
致謝
首先要感謝出版方對於我的信任和耐心,使得我能夠順利地完成本書的翻譯。在翻譯本書的同時,妻子云蘭正在準備著迎接我們的第一個孩子,感謝你和未出世的孩子,你們是我所有的動力。感謝我的父母,你們一直都在默默地支持著我。
聶雪軍
2006年8月於北京
推薦序
這是一本非常出色的書,當我差不多閱讀完全書後,才深刻意識到這本書的巨大價值。本書或許是第一本為那些對C++已經很熟悉的人們——了解C++的全部特性的人們——所寫的書。從語言特性到標準庫中的組件,再到編程技術,本書的內容安排方式是從一個主題直接跳到另一個主題,這不僅可以使讀者的思維處於某種活躍狀態,還可以始終保持注意力。這與編寫C++程式時遇到的情況是一樣的。在本書中,我們將討論一些相互關聯的C++特性,例如類的設計與虛函式的行為,疊代器約定與名字查找規則,賦值運算符函式與異常安全性,編譯依賴性與導出模板等。這些討論涵蓋了語言特性、標準庫組件和編程技術等多方面的內容,不僅豐富,而且精彩。
我將GotW 讀作“Gotcha”,這聽起來似乎比較合適。當我把自己對書中問題的解答與Sutter給出的解答相對照時,總會發現自己掉入了他(和C++)設定的陷阱中,雖然不太情願面對這一情況,但事實確實如此。每當我犯錯時,似乎都看到Herb在微笑地說著“Gotcha!”。有些人可能認為這是因為我對C++了解得不多,還有一些人可能認為這是因為C++太複雜了,不易掌握。而我的看法是,這正好說明了當使用C++進行編程時,必須對代碼進行細緻的思考。C++是一種功能強大的語言,它能夠幫助我們解決一些很複雜的問題,因此開發人員一定要儘可能從細處入手去研究這門語言及其標準庫,以及慣用編程模式等方面。本書討論主題的廣度,以及獨特的“問題/解答”內容組織方式,都將能幫助你做到這一點。
在C++新聞組上,有經驗的讀者都知道,要選出一位“每周大師”是非常困難的,而親身參與其中的人們則會有著更深的體會。雖然在網上每周只能產生一位大師,但在本書的幫助下,你很有希望在每次編程時都能寫出大師級的代碼。
Scott Meyers
1999年6月
序
Exceptional C++通過實例來闡述如何實現可靠的軟體開發。本書收錄了廣受歡迎的網上專欄Guru of the Week(或者簡稱為GotW)中前30個問題並對它們進行擴充,此外還補充了大量的其他材料。Guru of the Week論述了一系列完整的C++軟體開發問題及其解決方案,這些內容很好地闡釋了一些特殊的設計技術和編碼技術。
本書並不是編碼難題的集合,其目的是為了指導程式設計師如何正確地使用C++來實施企業級的軟體設計。本書使用了“問題/解答”這種形式來組織內容,因為我認為這是最有效的學習方法。通過這種方法可以使你了解隱藏在問題背後的設計思想,以及各種指導原則的適用場合。雖然本書列出的條款涵蓋了許多方面的主題,但你會注意到,有一些與企業級開發問題相關的主題將重複出現,特別是異常安全性、類和模組的合理設計,正確的代碼最佳化,以及編寫符合C++標準的可移植代碼。
我希望本書的內容能對你的日常工作有所幫助。此外,我還希望你能從本書中發現一些好的思維方式和編碼技術,並且在閱讀本書時會不時地發出“啊,太棒了”這樣的感嘆。畢竟,軟體工程不見得是枯燥乏味的。
如何閱讀本書
我假設你已經較好地掌握了C++的基本知識。如果還沒有的話,那么應該首先去閱讀一本優秀的C++入門書籍(可以選擇一些經典的著作,例如Bjarne Stroustrup的The C++ Programming Language,Third Edition 或者Stan Lippman與Josee Lajoie合著的C++ Primer, Third Edtion ),然後再閱讀一本介紹編程風格的書籍,例如Scott Meyers的經典著作Effctive C++ (我發現通過瀏覽器來閱讀電子書非常方便、有用)。
本書的每個條款都通過一個問題來引出,每個條款都有一個介紹性的標題,如下所示:
條款##:條款的標題 難度係數:X
通過條款的標題和難度係數(通常是在3到91/2之間的值,最大值為10),就可以大致了解將要學習的內容。注意,這裡的難度係數是基於我個人的理解給出的,因為我認為這個難度係數對於大多數人來說都比較合適。因此,你可能會發現某個難度係數為7的問題可能會比難度係數為5的問題要容易些。儘管如此,當你看到難度係數為91/2的問題時,最好還是做好充分準備。
你可以不按照章節順序來閱讀書中的內容和問題討論,但在本書中有幾個地方介紹的是“一系列”相關的問題,在講解這些問題的條款的標題中將出現“之一”“之二”等字眼——在有的系列中甚至出現了“之十”。對於這些系列來說,最好將它們作為一個整體來閱讀。
本書還提出了許多指導原則,下面這些術語如在指導原則中出現,則有著特殊的含義。
始終(always):該指導原則是絕對必要的,應該永遠都這么做。
優先(prefer):該指導原則通常是正確的,只有在特定情況下才不適用。
考慮(consider):該指導原則或許適用,或許不適用,需要視具體情況而定。
避免(avoid):該指導原則通常不是最好的,甚至可能是危險的。因此,應該去尋求其他的替代方法,並且只有在特殊情況下才套用這條指導原則。
從不(never):該指導原則非常糟糕,甚至無須考慮就可以直接拒絕使用。
最後,我還想再說一下書中的URL——網上的資料始終在不斷地變化和更新,特別是有些資料的變化和更新是我無法控制的。我們通常會趕在書籍印刷之前將這些網頁URL加入書中,以免這些URL失效;而當書籍被印刷出來並且在你的桌子上放了5年之後,這些URL的有效性就沒人關心了,這是很痛苦的事情。因此,當我需要在書中引用其他人的文章或者網址時,將通過我自己站點gotw上的URL來引用,並且站點上的這些連結只是包含了到真實網頁的重定向,這樣就能夠控制URL的有效性。當你發現本書中的某個連結不再有效時,那么請發E-mail告訴我,我將更新連結並重定向到新的網址(如果我還能找到這些網頁)或者說明這些URL不再有效(如果找不到的話)。通過這種方法,無論書籍的印刷媒介是什麼,書中的URL都是最新的。
本書的緣由:GotW和PeerDirect
C++ Guru of the Week這個系列已經經歷了很長的一段發展歷程。GotW最初是在1996年底創建的,用來為我們自己在PeerDirect公司的開發小組提供一些有趣的難題和學習課程。我編寫這個系列的目的是為了提供一種有趣的學習工具,內容包括如何合理地使用繼承以及異常安全性。隨著時間的推移,我還通過這個系列將C++標準會議上做出的一些修改告訴小組成員。此後,GotW就向普通的C++程式設計師開放,並被作為網上新聞組comp.lang.c++.moderated上的一個固定專欄,在這個新聞組中可以找到每一期的問題和解答(以及許多有趣的討論)。
在PeerDirect公司里,用好C++很重要,這與在其他公司中用好C++的理由是相同的,只不過所要實現的目標會有所不同。我們的主要工作是構建系統軟體——包括分散式資料庫以及資料庫的複製——其中像可靠性、安全性、可移植性、執行效率以及其他一些因素都是非常重要的。我們所編寫的軟體必須能夠在多種不同的編譯器和作業系統上進行移植;當發生資料庫事務死鎖、通信中斷或者程式異常時,這些軟體必須是安全的和健壯的。用戶可以使用這些軟體來管理位於智慧卡、自動售賣機或者PalmOS和WinCE設備上的微型資料庫,部門級的Windows NT、Linux和Solaris伺服器,以及支撐網頁伺服器和數據倉庫的大規模並行Oracle後台服務——我們實現這些功能時使用的是相同的軟體、相同的可靠性和相同的代碼。當編寫大量緊湊並且沒有注釋行的代碼時,可移植性和可靠性將是要面臨的巨大挑戰。
對於在過去幾年中一直在網上閱讀Guru of the Week系列的讀者,我想聲明兩件事情:
感謝你們的關注、支持、E-mail、讚賞、更正、意見、批評和問題——特別是你們希望將GotW系列彙編成書的要求。現在這本書已經完成了,希望你們能夠喜歡。
本書包含的內容要遠遠多於在網上給出的內容。
本書並不只是對網上原有的GotW問題進行簡單的複製和貼上,而是對所有問題和解答都進行了很大程度的修正和重新整理——例如,在條款8到條款17中關於異常安全性的討論,最初只是一個單獨的GotW問題,而現在已經變成了一個更為深入的,並且擁有10個條款的系列。每個問題和解答都經過了仔細的檢查,確保與現在正式的C++標準保持一致。
因此,如果你以前是GotW的固定讀者,那么在本書中仍然會看到大量新的內容。再次感謝所有忠實的讀者,另外,我希望本書還可以幫助你不斷地提升和擴充自己在軟體工程和C++編程等方面的技術。
致謝
首先要感謝在comp上所有的GotW熱心讀者,尤其是那些參與為本書取名的人們。特別感謝兩位對本書的最終名字有很大幫助的讀者:Macro Dalla Gasperine(建議的名字是Enlightented C++);Rob Stewart(建議的名字是Practical C++:Problems and Solutions)。由於我在本書中反覆強調了異常安全性,因此在這些名字的基礎上,我很自然地使用了“Exceptional”這個單詞。
我還要感謝叢書的編輯Bjarne Stroustrup,感謝Marina Lang,Debbie Lafferty以及其他Addison Wesley Longman出版公司的工作人員,感謝他們對本書的興趣和熱情,並感謝他們在1998年Santa Cruz召開的C++標準會議上舉行的招待會。
我還要感謝許多審閱本書的人們——其中許多人都是C++標準委員會的成員——他們提出了許多成熟而深刻的建議,這些建議對於本書的內容起到了很大的改進作用。特別感謝Bjarne Stroustrup,Scott Meyers,Andrei Alexandrescu,Steve Clamage,Steve Dewhurst,Cay Horstmann,Jim Hyslop,Brendan Kehoe以及Dennis Mancl,感謝他們寶貴的觀點和意見。
最後,我最需要感謝的是我的家人和朋友,他們通過各種各樣的方式始終陪伴著我。
Herb Sutter
1999年6月
目 錄
1 泛型程式設計與C++標準庫1
條款1:疊代器難度係數1
條款2:大小寫不敏感的字元串——之一5
條款3:大小寫不敏感的字元串——之二9
條款4:可重用性最高的泛型容器——之一12
條款5:可重用性最高的泛型容器——之二13
條款6:臨時對象22
條款7:標準庫的使用(或者,再論臨時對象)28
2 異常安全性相關的問題與技術31
條款8:編寫異常安全的代碼——之一32
條款9:編寫異常安全的代碼——之二37
條款10:編寫異常安全的代碼——之三40
條款11:編寫異常安全的代碼——之四47
條款12:編寫異常安全的代碼——之五50
條款13:編寫異常安全的代碼——之六56
條款14:編寫異常安全的代碼——之七62
條款15:編寫異常安全的代碼——之八65
條款16:編寫異常安全的代碼——之九68
條款17:編寫異常安全的代碼——之十73
條款18:代碼的複雜性——之一75
條款19:代碼的複雜性——之二79
3 類的設計與繼承85
條款20:類的編寫技巧85
條款21:虛函式的重載93
條款22:類之間的關係——之一99
條款23:類之間的關係——之二103
條款24:繼承的使用和濫用110
條款25:面向對象程式設計121
4 編譯器防火牆和Pimpl慣用法123
條款26:將編譯期依賴性降到最低——之一123
條款27:將編譯期依賴性降到最低——之二127
條款28:將編譯期依賴性降到最低——之三132
條款29:編譯防火牆135
條款30:Fast Pimpl慣用法138
5 名字查找、名字空間和接口規則148
條款31:名字查找與接口規則——之一148
條款32:名字查找與接口規則——之二152
條款33:名字查找和接口規則——之三162
條款34:名字查找與接口規則——之四167
6 記憶體管理176
條款35:記憶體管理——之一176
條款36:記憶體管理——之二179
條款37:AUTO_PTR186
7 誤區、陷阱以及錯誤的慣用法201
條款38:對象標識201
條款39:自動轉換204
條款40:對象的生存期——之一206
條款41:對象的生存期——之二209
8 其他主題219
條款42:變數的初始化219
條款43:正確使用const222
條款44:類型轉換231
條款45:BOOL238
條款46:轉調函式242
條款47:控制流程244
後記254
參考書目256