《STL擴展技術手冊(卷1):集合和疊代器》以STLSoft為基礎,廣泛深入地論述了C++標準庫STL的相關內容。全書共三部分43章,包括標準庫模板、擴展STL、元素引用類別、DRYSPOT原則、抽象泄漏法則、契約式編程、約束、墊片、不完備結構一致性的發端、資源獲取、模板工具、推斷式接口適配、Henney假說、適配、遍歷進程和模組、環境變數、字元串分詞、聚集分散的I/O以及疊代器等內容。 通過嚴謹的表述與豐富的示例,將概念和理論與實際的設計和代碼結合起來,從而使讀者既能深刻地理解STL的知識,又能熟練地掌握STL運用方法。
基本介紹
- 書名:STL擴展技術手冊
- 作者:威爾森 (Matthew Wilson)
- 出版社:機械工業出版社
- 頁數:414頁
- 開本:16
- 品牌:機械工業出版社
- 外文名:Extended STL, Volume 1: Collections and Iterators
- 譯者:金慶
- 出版日期:2008年9月1日
- 語種:簡體中文
- ISBN:7111242270, 9787111242277
基本介紹,內容簡介,作者簡介,媒體推薦,圖書目錄,文摘,序言,
基本介紹
內容簡介
著名的C++專家MatthewWilson在《STL擴展技術手冊(卷1):集合和疊代器》中展示了如何超越C++標準並擴展標準模板庫(StandardTemplateLibrary,STL),進入包含API和非標準集合的更廣闊的C++世界,以編寫更有效、更有表達力、更靈活、更健壯的軟體。
在《STL擴展技術手冊(卷1):集合和疊代器》中,Wilson使用自己創新的技術幫助讀者掌握STL擴展特性,這體現在兩個方面:將專用技術庫和作業系統API適配為STL兼容的集合,並定義精密的疊代適配器,使STL潛在的效率和表現力得以實現。Wilson用實際的例子闡明了幾個強大的概念和技巧,讓你在連STL的創造者都未曾預見的方向上擴展STL,其中包括集合、元素參考類別、外部疊代器失效和推斷式接口適配。
對於那些對STL知之甚微的C++程式設計師,《STL擴展技術手冊(卷1):集合和疊代器》將是寶貴的資源。
在《STL擴展技術手冊(卷1):集合和疊代器》中,Wilson使用自己創新的技術幫助讀者掌握STL擴展特性,這體現在兩個方面:將專用技術庫和作業系統API適配為STL兼容的集合,並定義精密的疊代適配器,使STL潛在的效率和表現力得以實現。Wilson用實際的例子闡明了幾個強大的概念和技巧,讓你在連STL的創造者都未曾預見的方向上擴展STL,其中包括集合、元素參考類別、外部疊代器失效和推斷式接口適配。
對於那些對STL知之甚微的C++程式設計師,《STL擴展技術手冊(卷1):集合和疊代器》將是寶貴的資源。
作者簡介
威爾森,MatthewWilsonSynesis軟體公司的軟體開發顧問,STLSoft和Pantheios庫的創建者,《ImperfectC++》(AddisonWesley)的作者,他曾是《C/C++UsersJournal》(C/C++用戶雜誌)的專欄作家,也是一些主要出版物的撰搞者,具有15年以上的C++經驗。他擁有英國曼徹斯特大學博士學位,目前定居在澳大利亞。
媒體推薦
“《Extended STL》不只是一本關於適應STL並用於日常工作的書,它也是一次冒險旅行,它帶你經歷軟體設計和概念、C++的強力技術,以及真實世界軟體開發中的危險,換句話說,它是一本Matthew Wilson風格的書。如果你對C++的態度是嚴肅認真的,我認為你應該閱讀它。”
—Bjorn Karlsson,主設計師,ReadSoft;《Beyond the C++ Standard Library: An Introduction to Boost》的作者
—Bjorn Karlsson,主設計師,ReadSoft;《Beyond the C++ Standard Library: An Introduction to Boost》的作者
圖書目錄
譯者序
前言
致謝
序言
編排體例
第一部分 基礎
第1章 標準模板庫
第2章 擴展STL:STL與真實世界的碰撞
第3章 元素引用類別
第4章 奇異去臨時引用
第5章 DRY SPOT原則
第6章 抽象泄漏法則
第7章 契約式編程
第8章 約束
第9章 墊片
第10章 鴨規則和鵝規則:不完備結構一致性的發端
第11章 資源獲取即初始化
第12章 模板工具
第13章 推斷式接口適配:編譯時適配接口不全的類型
第14章 Henney假說:當模板參數表太長
第15章 通過equal()減少友元函式的使用
第16章 基本組件
第二部分 集合
第17章 適配glob API
第18章 插曲:構造函式衝突以及不良的設計
第19章 適配opendir/readdir API
第20章 適配FindFirstFile/FindNextFile API
第21章 插曲:枚舉FTP伺服器目錄——保持效率和可用性的平衡
第22章 遍歷進程和模組
第23章 斐波那契序列
第24章 適配MFC的CArray容器族
第25章 環境變數的map
第26章 在Z平面上來回穿梭
第27章 字元串分詞
第28章 適配COM枚舉器
第29章 插曲:運用成員類型推斷,糾正設計上的小疏忽
第30章 適配COM集合
第31章 聚集分散的I/O
第32章 根據參數返回不同類型
第33章 外部疊代器失效
第三部分 疊代器
第34章 增強版ostream_iterator
第35章 插曲:藉助解引用代理模式,消除笨拙的輸出疊代器語法
第36章 變換疊代器
第37章 插曲:命名時謹慎為好
第38章 成員選取疊代器
第39章 連線C風格字元串
第40章 字元串對象的連線操作
第41章 適配疊代器特徵類
第42章 過濾疊代
第43章 組合多個疊代器適配
結語
參考書目
前言
致謝
序言
編排體例
第一部分 基礎
第1章 標準模板庫
第2章 擴展STL:STL與真實世界的碰撞
第3章 元素引用類別
第4章 奇異去臨時引用
第5章 DRY SPOT原則
第6章 抽象泄漏法則
第7章 契約式編程
第8章 約束
第9章 墊片
第10章 鴨規則和鵝規則:不完備結構一致性的發端
第11章 資源獲取即初始化
第12章 模板工具
第13章 推斷式接口適配:編譯時適配接口不全的類型
第14章 Henney假說:當模板參數表太長
第15章 通過equal()減少友元函式的使用
第16章 基本組件
第二部分 集合
第17章 適配glob API
第18章 插曲:構造函式衝突以及不良的設計
第19章 適配opendir/readdir API
第20章 適配FindFirstFile/FindNextFile API
第21章 插曲:枚舉FTP伺服器目錄——保持效率和可用性的平衡
第22章 遍歷進程和模組
第23章 斐波那契序列
第24章 適配MFC的CArray容器族
第25章 環境變數的map
第26章 在Z平面上來回穿梭
第27章 字元串分詞
第28章 適配COM枚舉器
第29章 插曲:運用成員類型推斷,糾正設計上的小疏忽
第30章 適配COM集合
第31章 聚集分散的I/O
第32章 根據參數返回不同類型
第33章 外部疊代器失效
第三部分 疊代器
第34章 增強版ostream_iterator
第35章 插曲:藉助解引用代理模式,消除笨拙的輸出疊代器語法
第36章 變換疊代器
第37章 插曲:命名時謹慎為好
第38章 成員選取疊代器
第39章 連線C風格字元串
第40章 字元串對象的連線操作
第41章 適配疊代器特徵類
第42章 過濾疊代
第43章 組合多個疊代器適配
結語
參考書目
文摘
第2章.擴展STL:STL與真實世界的碰撞
好的定律是清楚和簡單的,並讓使用者在面對具體問題時應對自如。
-RonMcCallum教授
搞清楚你此刻應當做什麼,然後去做。
-BillyConnolly
前章涵蓋了STL的要點,包括容器、疊代器、算法、函式對象、分配器及適配器的核心概念。可惜擴展STL時,這些概念不是太抽象就是太粗糙。這一章中我們將針對本卷中關於集合及疊代器適配器的材料,進一步探討這些概念。
2.1.術語
雖然標準庫中包含了許多原STL(Stepanov與同事開發的版本)的內容,但卻(還)沒有全盤照搬。比方說C++03標準目前只定義了基於樹的關聯容器,而沒有包含原STL中基於hash表的關聯容器。儘管已經有建議要加入此類容器,並且會在下個C++標準發布時被採納,但眼下的狀況就是標準庫並非STL的超集。
另一方面,標準庫中包含不屬於STL但卻與STL兼容的組件,即IOStreams。當把IOStreams看作嚴肅的I/O程式庫,無論從哪方面考量,附著其上的STL兼容接口都對C++有利無害。
STL與標準庫有許多重疊的地方,但兩者卻又是不同的。在這一卷中,我不去理會任何未被標準庫採納的STL組件,反之亦然。所以,當我提到“標準組件”的時候,我的意思是指那些既在STL庫又在標準庫中,且定義與標準庫定義一致的組件。
本書主要討論的是擴展STL的技術,我們還需要一套術語才能進行下去,這些擴展不僅是增加新容器而已。事實上,大部分擴展提供的是對一個區間內的元素的訪問手段,但它們根本不是容器,我稱它們為STL集合。我們在下一個小節中討論集合概念,及其與容器概念的關係。
2.2.集合
STL本身只關注容器。標準把容器定義為“存儲別的對象,[同時]對這些對象負有分配及回收的責任,途徑是對象的構造函式,析構函式,插入操作以及刪除操作”(C++-03:23.1;1)。但是有比容器多得多的類型屬於對象集合(圖2.1)。在本書所有後續章節,特別是在第二部分中,我將使用在本章中定義的分類。
好的定律是清楚和簡單的,並讓使用者在面對具體問題時應對自如。
-RonMcCallum教授
搞清楚你此刻應當做什麼,然後去做。
-BillyConnolly
前章涵蓋了STL的要點,包括容器、疊代器、算法、函式對象、分配器及適配器的核心概念。可惜擴展STL時,這些概念不是太抽象就是太粗糙。這一章中我們將針對本卷中關於集合及疊代器適配器的材料,進一步探討這些概念。
2.1.術語
雖然標準庫中包含了許多原STL(Stepanov與同事開發的版本)的內容,但卻(還)沒有全盤照搬。比方說C++03標準目前只定義了基於樹的關聯容器,而沒有包含原STL中基於hash表的關聯容器。儘管已經有建議要加入此類容器,並且會在下個C++標準發布時被採納,但眼下的狀況就是標準庫並非STL的超集。
另一方面,標準庫中包含不屬於STL但卻與STL兼容的組件,即IOStreams。當把IOStreams看作嚴肅的I/O程式庫,無論從哪方面考量,附著其上的STL兼容接口都對C++有利無害。
STL與標準庫有許多重疊的地方,但兩者卻又是不同的。在這一卷中,我不去理會任何未被標準庫採納的STL組件,反之亦然。所以,當我提到“標準組件”的時候,我的意思是指那些既在STL庫又在標準庫中,且定義與標準庫定義一致的組件。
本書主要討論的是擴展STL的技術,我們還需要一套術語才能進行下去,這些擴展不僅是增加新容器而已。事實上,大部分擴展提供的是對一個區間內的元素的訪問手段,但它們根本不是容器,我稱它們為STL集合。我們在下一個小節中討論集合概念,及其與容器概念的關係。
2.2.集合
STL本身只關注容器。標準把容器定義為“存儲別的對象,[同時]對這些對象負有分配及回收的責任,途徑是對象的構造函式,析構函式,插入操作以及刪除操作”(C++-03:23.1;1)。但是有比容器多得多的類型屬於對象集合(圖2.1)。在本書所有後續章節,特別是在第二部分中,我將使用在本章中定義的分類。
序言
難道每門語言都難免日趨複雜,並最終絆倒在複雜性的門檻上嗎?
—AdamConnor
難用的話,少用就是了。
—MelanieKrug
事物的兩面性
3年前,《ImperfectC++》快要完工時,我跟編輯說起這本《ExtendedSTL》,當時我信心滿滿地聲稱它會是一本易讀易懂。且輕薄短小得可以輕鬆從兩個抽象層之間滑過的小冊子。此外我還保證會在半年之內寫完。結果呢?在寫這篇序言的時候,離當初約好的截稿日期已經過去了一年半有餘,而且,本來計畫好的一本薄薄的。約十六至二十個章節的小冊子現在也膨脹成了兩卷本,其中第一卷洋洋灑灑四十三個章節(含“插曲”章節),喔,對了,CD上還有三章呢…但話說回來,當初有一個保證現在仍然可以說是成立的,那就是這是一本對任何有一定C++經驗的讀者來說都輕鬆易懂的書。
為什麼這本書後來的情況遠遠超出我當初的預計呢?並不是因為我是軟體工程師——大家都知道軟體工程師估計的工作量,乘三之後才是實際需要的時間。而是因為(我認為)以下四個重要的原因:
1。STL並不直觀,花費可觀的智力投資後方能熟練運用。
2。沒錯,STL在技術上功臻化境,沒錯,STL在內聚性方面超凡入聖。然而,STL前瞻性不夠,對於在它那有限的概念定義之外的抽象,它並不能妥善應付。
3。C++語言本身是不完美的。
4。C++是一門難學的語言,但你得到的回報是效率,而且同時又並沒有犧牲設計。
最近幾年C++與時俱進,這一方面意味著C++變得非常強大,但另一方面也暴露出了其晦澀難懂的一面。如果你試著編寫一個具有一定規模並用到模板元編程的模板庫,那么一種可能是你將學到許多東西,並掌握了一個強大的工具,但同樣也很可能的是你編寫出的那堆東西除了C++狂熱信徒之外誰也無法理解。
C++的使用精神本來就是擴展。除了很有限的一些套用是將C++看作“更好的C”來使用的之外,絕大多數C++使用都是圍繞著類型定義(類。枚舉。結構。聯合)來進行的,而且這些自定義類型很大程度上被做成與內建類型界面一致。也正因為這個原因,C++中的許多內建操作符都是允許重載的。這樣,一個vector,比如說,便可以重載operator[]來模擬內建數組的界面,再舉個例子:任何可被拷貝(Copyable)的類型(一般)都定義(重載)了拷貝賦值操作符(operator=)。如此等等,不一而足。但由於C++的不完美。強大。以及極強的可擴展性,伴隨而來的便是JoelSpolsky所說的抽象滲漏法則(theLawofLeakyAbstractions):“所有非平凡的抽象在某種程度上都是有漏洞的。”簡單來說這句話就意味著要想順利使用非平凡的抽象就必須對抽象下面的東西有所了解。
這也正是許多C++開發者重新發明輪子的原因之一。其實這裡的原因並不僅僅是眾所周知的所謂“非我發明症”(NIH),而是因為我們常常發現自己所用的第三方組件除了百分之八十的功能是自己能理解並使用的之外,剩下的百分之二十往往裹著一團晦澀的黑氣,造成後者的原因很多:複雜性。與既有概念或慣用法的不一致。低效。效率。範圍局限性。設計或實現的不優雅。糟糕的編碼風格等等。而且,編譯技術現階段的一些實際問題還會極大地加劇這種情況,尤其是遇到模板實例化過程中的錯誤訊息時。
我覺得我之所以有資格寫這本書,原因之一就是我花了大量的時間來研究並實現STL相關的庫,而不是接受C++標準(1998)所指定的庫或其他人寫的庫。而我決定寫這本書的原因之一則是想將我在以上過程中學到的東西總結出來。如果你想要編寫STL擴展,這本書可以為你提供幫助,而就算你只是想使用其他人寫的STL擴展,這本書也同樣有用,因為抽象滲漏法則決定了你很可能會不時需要掀開抽象這塊幕布往裡面瞧一瞧。
UNIX編程的原則
在《UNIX程式設計藝術》(Addison-Wesley,2004)中,EricRaymond總結了UNIX社群的最佳實踐準則,這些準則來自大量不同的經驗。在我們改裝STL的宏大計畫中,這些準則就像標燈一樣為我們指明方向:
·清晰原則:清晰比巧妙重要。
·組合原則:設計能夠互相連線的組件。
·多樣性原則:質疑任何被聲稱為“真正唯一”的途徑。
·經濟原則:程式設計師時間是昂貴的,在它跟機器時間之間,優先節省前者。
·可擴展性原則:在未來時態下設計,因為未來比你想像得來得更快。
·生成原則:避免手動編碼,可以的話,編寫程式來生成程式。
·最小意外原則:在接口設計中作出的決策應該始終是那個令人最少感到意外的選擇。
·模組性原則:編寫簡單的模組,模組與模組間通過乾淨的接口連線。
·最大意外原則:如果免不了要失敗的話,要弄出最大動靜,而且失敗得越早越好。
·最佳化原則:首先要能工作,然後才能談得上最佳化。
·PrincipleofParsimony:Writelargecomponentsonlywhenitisclearbydemonstrationthatnothingelsewilldo。
·吝嗇原則:除非能夠明確證明別無它法,否則不要編寫大的組件。
·健壯性原則:透明性和簡單性是健壯性的父母。
·分離原則:策略和機制分離,接口與引擎分離。
·簡單原則:設計應該是簡單的,只在必須的時候才增加或暴露複雜性。
·透明原則:設計的時候應考慮透明性,以方便檢查和調試。
—AdamConnor
難用的話,少用就是了。
—MelanieKrug
事物的兩面性
3年前,《ImperfectC++》快要完工時,我跟編輯說起這本《ExtendedSTL》,當時我信心滿滿地聲稱它會是一本易讀易懂。且輕薄短小得可以輕鬆從兩個抽象層之間滑過的小冊子。此外我還保證會在半年之內寫完。結果呢?在寫這篇序言的時候,離當初約好的截稿日期已經過去了一年半有餘,而且,本來計畫好的一本薄薄的。約十六至二十個章節的小冊子現在也膨脹成了兩卷本,其中第一卷洋洋灑灑四十三個章節(含“插曲”章節),喔,對了,CD上還有三章呢…但話說回來,當初有一個保證現在仍然可以說是成立的,那就是這是一本對任何有一定C++經驗的讀者來說都輕鬆易懂的書。
為什麼這本書後來的情況遠遠超出我當初的預計呢?並不是因為我是軟體工程師——大家都知道軟體工程師估計的工作量,乘三之後才是實際需要的時間。而是因為(我認為)以下四個重要的原因:
1。STL並不直觀,花費可觀的智力投資後方能熟練運用。
2。沒錯,STL在技術上功臻化境,沒錯,STL在內聚性方面超凡入聖。然而,STL前瞻性不夠,對於在它那有限的概念定義之外的抽象,它並不能妥善應付。
3。C++語言本身是不完美的。
4。C++是一門難學的語言,但你得到的回報是效率,而且同時又並沒有犧牲設計。
最近幾年C++與時俱進,這一方面意味著C++變得非常強大,但另一方面也暴露出了其晦澀難懂的一面。如果你試著編寫一個具有一定規模並用到模板元編程的模板庫,那么一種可能是你將學到許多東西,並掌握了一個強大的工具,但同樣也很可能的是你編寫出的那堆東西除了C++狂熱信徒之外誰也無法理解。
C++的使用精神本來就是擴展。除了很有限的一些套用是將C++看作“更好的C”來使用的之外,絕大多數C++使用都是圍繞著類型定義(類。枚舉。結構。聯合)來進行的,而且這些自定義類型很大程度上被做成與內建類型界面一致。也正因為這個原因,C++中的許多內建操作符都是允許重載的。這樣,一個vector,比如說,便可以重載operator[]來模擬內建數組的界面,再舉個例子:任何可被拷貝(Copyable)的類型(一般)都定義(重載)了拷貝賦值操作符(operator=)。如此等等,不一而足。但由於C++的不完美。強大。以及極強的可擴展性,伴隨而來的便是JoelSpolsky所說的抽象滲漏法則(theLawofLeakyAbstractions):“所有非平凡的抽象在某種程度上都是有漏洞的。”簡單來說這句話就意味著要想順利使用非平凡的抽象就必須對抽象下面的東西有所了解。
這也正是許多C++開發者重新發明輪子的原因之一。其實這裡的原因並不僅僅是眾所周知的所謂“非我發明症”(NIH),而是因為我們常常發現自己所用的第三方組件除了百分之八十的功能是自己能理解並使用的之外,剩下的百分之二十往往裹著一團晦澀的黑氣,造成後者的原因很多:複雜性。與既有概念或慣用法的不一致。低效。效率。範圍局限性。設計或實現的不優雅。糟糕的編碼風格等等。而且,編譯技術現階段的一些實際問題還會極大地加劇這種情況,尤其是遇到模板實例化過程中的錯誤訊息時。
我覺得我之所以有資格寫這本書,原因之一就是我花了大量的時間來研究並實現STL相關的庫,而不是接受C++標準(1998)所指定的庫或其他人寫的庫。而我決定寫這本書的原因之一則是想將我在以上過程中學到的東西總結出來。如果你想要編寫STL擴展,這本書可以為你提供幫助,而就算你只是想使用其他人寫的STL擴展,這本書也同樣有用,因為抽象滲漏法則決定了你很可能會不時需要掀開抽象這塊幕布往裡面瞧一瞧。
UNIX編程的原則
在《UNIX程式設計藝術》(Addison-Wesley,2004)中,EricRaymond總結了UNIX社群的最佳實踐準則,這些準則來自大量不同的經驗。在我們改裝STL的宏大計畫中,這些準則就像標燈一樣為我們指明方向:
·清晰原則:清晰比巧妙重要。
·組合原則:設計能夠互相連線的組件。
·多樣性原則:質疑任何被聲稱為“真正唯一”的途徑。
·經濟原則:程式設計師時間是昂貴的,在它跟機器時間之間,優先節省前者。
·可擴展性原則:在未來時態下設計,因為未來比你想像得來得更快。
·生成原則:避免手動編碼,可以的話,編寫程式來生成程式。
·最小意外原則:在接口設計中作出的決策應該始終是那個令人最少感到意外的選擇。
·模組性原則:編寫簡單的模組,模組與模組間通過乾淨的接口連線。
·最大意外原則:如果免不了要失敗的話,要弄出最大動靜,而且失敗得越早越好。
·最佳化原則:首先要能工作,然後才能談得上最佳化。
·PrincipleofParsimony:Writelargecomponentsonlywhenitisclearbydemonstrationthatnothingelsewilldo。
·吝嗇原則:除非能夠明確證明別無它法,否則不要編寫大的組件。
·健壯性原則:透明性和簡單性是健壯性的父母。
·分離原則:策略和機制分離,接口與引擎分離。
·簡單原則:設計應該是簡單的,只在必須的時候才增加或暴露複雜性。
·透明原則:設計的時候應考慮透明性,以方便檢查和調試。