第一章 STL概論與版本簡介
1.1 STL概論
爲了複用性的提升,爲了建立數據結構和算法的一套標準,並且降低其間的耦合(coupling)關係以提升各自的獨立性、彈性、交互操作性(interoperability),C++社羣裏面誕生了STL。
STL的價值
- 低層次
- 一套極具實用價值的零部件
- 一個整合的組織
- 高層次
- 以泛型思維(Generic Paradigm)爲基礎、系統化的、條理分明的“軟件組件分類學(componens taxonomy)”
- 具體敘述了抽象概念並加以系統化
1.1.1 STL的歷史
STL由Alexander Stepanov創造於1979年前後,這也正是Bjarne Stroustrup創造C++的年代。第一個支持泛型概念的語言是Ada。當時C++尚未導入template性質,但C++允許程序員通過指針以極佳彈性處理內存,這一點正是既要求一般化(泛型)又不失效能的一個重要關鍵。
Alexander在AT&T實驗室以及惠普公司的帕羅奧圖實驗室,分別實驗了多種架構和算法公式,先以C完成,而後再以C++完成。1992年Meng Lee加入Alex的項目,成爲STL的另一位主要貢獻者。
貝爾(Bell)實驗室的Andrew Koening於1993年知道這個研究計劃後,邀請Alexander於11月ANSI/ISO C++標準委員會會議上展現其觀念。並於次年夏天的Waterloo(滑鐵盧)會議開幕前,完成正式提案,並以壓倒性多數一舉讓這個巨大的計劃成爲C++標準規格的一部分。
1.1.2 STL與C++標準程序庫
1993年9月,Alexander Stepanov和他一手創建的STL,與C++標準委員會有了第一次接觸。
1994年1月6日Alexander收到Andy Koening(C++標準委員會成員,當時的C++ Standard文件審覈編輯)來信,言明如果希望STL成爲C++標準程序庫的一部分,可於1994年1月25日之前送交一份提案報告到委員會。
1994年3月聖地亞哥會議。STL在會議上取得很好的迴響,但也有反對意見。主要反對意見是C++即將完成最終草案,而STL卻是如此龐大,似乎有點時不我予。
然後就是Waterloo會議,80%贊成20%反對,終於進入C++標準化的正式流程,併成爲1998年9月定案的C++標準規格中的一大派系。原有的C++程序庫,如stream,string等也都以template重新寫過。
1.2 STL六大組件 功能與運用
STL提供六大組件,彼此可以組合套用:
- 容器(containers):各種數據結構,如vector,list,deque,set,map,用來存放數據。從實現的角度來 看,STL容器是一種class template。就體積而言,這一部分很像冰山在海面下的比率。
- 算法(algorithms):箇中國常用算法如sort,search,copy,erase……。從實現角度來看,STL算法是一種 function template。
- 迭代器(iterators):扮演容器與算法之間的膠合劑,是所謂的“泛型指針”。共有五種類型,以及其他衍生 變化。從實現角度看,迭代器是一種將operator*,operator->,operator++,operater–等指針相關操作予 以重載的class template。所有STL容器都附帶有自己專屬的迭代器。原生指針也是一種迭代器。
- 仿函數(functors):行爲類似函數,可作爲算法的某種策略(policy)。從實現的角度來看,仿函數是一種重載了operator()的class或class template,一般函數指針可視爲狹義的仿函數。
- 配接器(adapters): 一種用來修飾容器(containers)或仿函數(functors)或迭代器(iterators)接口的東西。例如STL提供的queue和stack,雖然看似容器,其實只能算是一種容器配接器,因爲它們的底部完全藉助deque,所有操作都由底層的deque供應。
- 配置器(allocators):負責空間配置與管理。從實現的角度來看,配置器是一個實現了動態空間配置、空間管理、空間釋放的class template。
由於STL已經成爲C++標準程序庫的大脈系,目前所有C++編譯器一定支持有一份STL,在C++頭文件(headers)中,按照C++ Standard 的規定,所有標準文件都不再有擴展名,某些STL版本同時存在具有擴展名和無擴展名的兩份文件。某些只存在具擴展名的頭文件。某些STL版本不僅有一線裝配,還有二線裝配,例如GNU C++的SGI版本不但有一線的<vector.h>和,還有二線的<stl_vector.h>
1.3 GNU源代碼的開放精神
全世界所有的STL實現版本,都源於Alexander Stepanov 和 Meng Lee完成的原始版本,這份原始版本由Hewlett-Packard Company(惠普公司)擁有。每一個頭文件都有一份聲明,允許任何人任意運用、拷貝、修改、傳播、販賣這些代碼,無需付費,唯一的條件是必須將該份聲明置於使用者新開發的文件內。
開源精神(open source)源於美國人Richard Stallman(理查德·史託曼)。他於1984年離開麻省理工學院,創立自由軟件基金會(Free Software Foundation,簡稱FSF),寫下著名的GNU宣言(GNU Manifesto)。
GNU這個名稱代表GNU is Not Unix。
GNU計劃中,早期最著名的軟件包括Emacs和GCC,前者是Stallman開發的一個非常靈活的文本編譯器,後者是一個C/C++編譯器。GNU計劃晚近的著名軟件則是1991年由芬蘭人Linus Torvalds開發的Linux操作系統。
GNU以所謂的GPL(General Public License,廣泛開放授權)來保護其成員,甚至被稱爲反版權(copyleft)。
自1999年起,EGCS(Experimental/Enhanced GNU Compiler System)正式成爲唯一的GCC官方維護機構。
1.4 HP實現版本
屬於open source,但不屬於GNU GPL範疇。
1.5 P.J.Plauger實現版本
P.J.Plauger版本由P.J.Plauger開發,繼承自HP版本,除了HP版本聲明還加上了P.J.Plauger的個人版權聲明。這個版本不屬於open source範疇,更不是GNU GPL。
P.J.Plauger版本被Virtual C+採用,可以在“include”子目錄下找到所有的STL頭文件,但是不能公開它或修改它或甚至販賣它。
1.6 Rouge Wave實現版本
被C++ Builder採用,不屬於open source範疇。
1.7 STLport實現版本
1.8 SGI STL實現版本
SGI版本被GCC採用,可以在GCC的“include”子目錄下找到所有STL頭文件。
1.8.1 GNU C++ headers文件分佈
共128個文件
1.8.2 SGI STL文件分佈與簡介
- C++標準規範下的C頭文件(無擴展名),例如 cstdio,cstdlib,cstring
- C++標準程序庫中不屬於STL範疇者,例如Stream,string……相關文件。
- STL標準頭文件(無擴展名),例如 vector,deque,list,map,algorithm,functional……
- C++ Standard定案前,HP所規範的STL頭文件,例如 vector.h,deque.h,list.h,map.h,algo.h,functon.h……
- SGI STL 內部文件(STL真正實現於此),例如stl_vector.h,stl_deque.h,stl_list.h,stl_map.h,stl_algo.h,stl_function.h……
其中後三組頭文件詳細列表於下
(1) STL標準頭文件(無擴展名)
文件名(按字母排序) | 本書章節 | 說明 |
---|---|---|
algorithm | ref.<stl_algorithm.h> |
|
deque | ref.<stl_deque.h> |
|
functional | ref.<stl_function.h> |
|
hash_map | ref.<stl_hash_map.h> |
|
hash_set | ref.<stl_hash_set.h> |
|
iterator | ref.<stl_iterator.h> |
|
list | ref.<stl_list.h> |
|
map | ref.<stl_nap.h> |
|
memory | 3.2 | 定義auto_ptr,幷包含<stl_algobase.h> ,<stl_alloc.h> ,<stl_construct.h> ,<stl_tempbuf.h> ,<stl_uninitialized.h> ,<stl_raw_storage_iter.h> |
numeric | ref.<stl_numeric.h> |
|
pthread_alloc | N/A | 與pthread相關node allocator |
queue | ref.<stl_queue.h> |
|
rope | ref.<stl_rope.h> |
|
set | ref.<stlset.h> |
|
slist | ref.<stl_slist.h> |
|
stack | ref.<stl_stack.h> |
|
utility | 包含<stl_relops.h>,<stl_pair.h> |
|
vector | ref.<stl_vector.h> |
(2) C++ Standard定案前,HP規範的STL文件名(擴展名.h)
文件名(按字母排序) | 本書章節 | 說明 |
---|---|---|
complex.h | N/A | 複數,包含<complex> 包含STL標準頭文件 <algorithm>,<br><deque>,<functional>, <iterator>,<list>,<map>, <memory>,<numeric>,<set>, <stack>,<utility>,<vectory> |
type_traits.h | 3.7 | SGI 獨特的type-traits技法 |
algo.h | ref.<stl_algo.h> |
|
algobase.h | ref.<stl_algobase.h> |
|
alloc.h | ref.<stl_alloc.h> |
|
bvector.h | ref.<stl_bvector.h> |
|
defalloc | 2.2.1 | 標準空間配置器std::allocator, 不建議使用 |
deque.h | ref.<stl_deque.h> |
|
function.h | ref.<stl_function.h> |
|
hash_map.h | ref.<stl_hash_map.h> |
|
hash_set.h | ref.<stl_hash_set.h> |
|
hashtable.h | ref.<stl_hashtable.h> |
|
heap.h | ref.<stl_heap.h> |
|
iterator.h | ref.<stl_iterator.h> |
|
list.h | ref<stl_list.h> |
|
map.h | ref.<stl_map.h> |
|
multimap.h | ref.<stl_multimap.h> |
|
multiset.h | ref.<stl_multiset.h> |
|
pair.h | ref.<stl_pair.h> |
|
pthread_alloc.h | N/A | #include <pthread_alloc> |
rope.h | ref.<stl_rope.h> |
|
set.h | ref.<stl_set.h> |
|
slist.h | ref.<stl_set.h> |
|
stack.h | ref.<stl_stack.h> |
|
tempbuf.h | ref.<stl_tempbuf.h> |
|
tree.h | ref.<stl_tree.h> |
|
vector.h | ref.<stl_vector.h> |
(3) SGI STL 內部私用文件(SGI STL真正實現於此)
文件名(按字母排序) | 本書章節 | 說明 |
---|---|---|
stl_algo.h | 6 | 算法(數值類除外) |
stl_algobase.h | 6.4 | 基本算法swap,min,max,copy, copy_backword,copy_n,fill, fill_n,mismath,equal, lexicograph,cal_compare |
stl_alloc.h | 2 | 空間配置器std::alloc |
stl_bvector.h | N/A | bit_vector(類似標準的bitset) |
stl_config.h | 1.9.1 | 針對各家編譯器特性定義各種環節變量 |
stl_construct.h | 2.2.3 | 構造/析構基本工具 (construct(),destroy()) |
stl_deque.h | 4.4 | deque(雙向開口的queue) |
stl_function.h | 7 | 函數對象(function object) 或稱仿函數(functor) |
stl_hash_fun.h | 5.6.7 | hash function |
stl_hash_map.h | 5.8 | 以hast-table完成之map,multimap |
stl_hash_set.h | 5.7 | 以hast-table完成之set,multiset |
stl_hashtable.h | 5.6 | hast-table(雜湊表) |
stl_iterator.h | 3.8.4 8.5 | 迭代器及其相關配接器,並定義迭代器 常用函數advance(),distance() |
stl_list.h | 4.3 | list(串行,雙向) |
stl_map.h | 5.3 | map(映象表) |
stl_multimap.h | 5.5 | multi-map(多鍵映象表) |
stl_multiset.h | 5.4 | multi-set(多鍵集合) |
stl_numeric.h | 6.3 | 數值類算法:accumulate, inner_product,partial_sum, adjacent_difference,power, iota |
stl_pair.h | 5.4 | pair(成對組合) |
stl_queue.h | 4.6 | queue(隊列) |
stl_raw_storage_iter.h | N/A | 定義raw_storage_iterator (一種 OutputIterator) |
stl_rope.h | N/A | 大型(巨量規模)的字符串 |
stl_set.h | 5.2 | set(集合) |
stl_slist.h | 4.9 | single list(單向串行) |
stl_stack.h | 4.5 | stack(堆棧) |
stl_tempbuf.h | N/A | 定義temporary_buffer class, 應用於 <stl_algo.h> |
stl_tree.h | 5.1 | Red Black tree(紅黑樹) |
stl_uninitialized.h | 2.3 | 內存管理基本工具: uninitialized_copy, uninitialized_fill, uninitialized_fill_n. |
stl_vector.h | 4.2 | vector(向量) |
1.8.3 SGI STL的編譯器組態設置(configuration)
不同的編譯器對C++語言的支持程度不同,準備了一個環境組態文件<stl_config.h>
,其中定義了許多常量來標示某些組態成立與否。所有STL頭文件都會包含這個組態文件,並以條件寫法讓預編譯器根據常量取捨哪一段程序代碼。