轉自原文http://blog.csdn.net/sxhelijian/article/details/7552499
C++強大的功能來源於其豐富的類庫及庫函數資源。C++標准庫的內容總共在50個標准頭文件中定義。在C++開發中,要盡可能地利用標准庫完成。這樣做的直接好處包括:(1)成本:已經作為標准提供,何苦再花費時間、人力重新開發呢;(2)質量:標准庫的都是經過嚴格測試的,正確性有保證;(3)效率:關於人的效率已經體現在成本中了,關於代碼的執行效率要相信實現標准庫的大牛們的水平;(4)良好的編程風格:采用行業中普遍的做法進行開發。
在C++程序設計課程中,尤其是作為第一門程序設計課程,我們注重了語法、語言的機制等方面的內容。程序設計能力的培養有個過程,跨過基本的原理性知識直接進入到工程中的普遍做法,由於跨度決定了其難度。再者,在掌握了基本原理的基礎上,在認識標准庫的問題上完全可以憑借實踐,逐步地掌握。標准庫的學習不需要認認真真地讀書,需要的是在了解概貌的情況下,在實踐中深入。
這個任務就是要知道C++程序設計課程中不講的,但對程序設計又很重要的這部分內容。至少我們要能先回答出“有什么”的問題。
一、C++標准庫
C++標准庫的內容分為10類,分別是(建議在閱讀中,將你已經用過或聽說過的頭文件划出來):
C1. 標准庫中與語言支持功能相關的頭文件
頭文件 |
描 述 |
<cstddef> |
定義宏NULL和offsetof,以及其他標准類型size_t和ptrdiff_t。與對應的標准C頭文件的區別是,NULL是C++空指針常量的補充定義,宏offsetof接受結構或者聯合類型參數,只要他們沒有成員指針類型的非靜態成員即可。 |
<limits> |
提供與基本數據類型相關的定義。例如,對於每個數值數據類型,它定義了可以表示出來的最大值和最小值以及二進制數字的位數。 |
<climits> |
提供與基本整數數據類型相關的C樣式定義。這些信息的C++樣式定義在<limits>中 |
<cfloat> |
提供與基本浮點型數據類型相關的C樣式定義。這些信息的C++樣式定義在<limits>中 |
<cstdlib> |
提供支持程序啟動和終止的宏和函數。這個頭文件還聲明了許多其他雜項函數,例如搜索和排序函數,從字符串轉換為數值等函數。它與對應的標准C頭文件stdlib.h不同,定義了abort(void)。abort()函數還有額外的功能,它不為靜態或自動對象調用析構函數,也不調用傳給atexit()函數的函數。它還定義了exit()函數的額外功能,可以釋放靜態對象,以注冊的逆序調用用atexit()注冊的函數。清除並關閉所有打開的C流,把控制權返回給主機環境。 |
<new> |
支持動態內存分配 |
<typeinfo> |
支持變量在運行期間的類型標識 |
<exception> |
支持異常處理,這是處理程序中可能發生的錯誤的一種方式 |
<cstdarg> |
支持接受數量可變的參數的函數。即在調用函數時,可以給函數傳送數量不等的數據項。它定義了宏va_arg、va_end、va_start以及va_list類型 |
<csetjmp> |
為C樣式的非本地跳躍提供函數。這些函數在C++中不常用 |
<csignal> |
為中斷處理提供C樣式支持 |
C2. 支持流輸入/輸出的頭文件
頭文件 |
描 述 |
<iostream> |
支持標准流cin、cout、cerr和clog的輸入和輸出,它還支持多字節字符標准流wcin、wcout、wcerr和wclog。 |
<iomanip> |
提供操縱程序,允許改變流的狀態,從而改變輸出的格式。 |
<ios> |
定義iostream的基類 |
<istream> |
為管理輸出流緩存區的輸入定義模板類 |
<ostream> |
為管理輸出流緩存區的輸出定義模板類 |
<sstream> |
支持字符串的流輸入輸出 |
<fstream> |
支持文件的流輸入輸出 |
<iosfwd> |
為輸入輸出對象提供向前的聲明 |
<streambuf> |
支持流輸入和輸出的緩存 |
<cstdio> |
為標准流提供C樣式的輸入和輸出 |
<cwchar> |
支持多字節字符的C樣式輸入輸出 |
C3. 與診斷功能相關的頭文件
頭文件 |
描 述 |
<stdexcept> |
定義標准異常。異常是處理錯誤的方式 |
<cassert> |
定義斷言宏,用於檢查運行期間的情形 |
<cerrno> |
支持C樣式的錯誤信息 |
C4. 定義工具函數的頭文件
頭文件 |
描 述 |
<utility> |
定義重載的關系運算符,簡化關系運算符的寫入,它還定義了pair類型,該類型是一種模板類型,可以存儲一對值。這些功能在庫的其他地方使用 |
<functional> |
定義了許多函數對象類型和支持函數對象的功能,函數對象是支持operator()()函數調用運算符的任意對象 |
<memory> |
給容器、管理內存的函數和auto_ptr模板類定義標准內存分配器 |
<ctime> |
支持系統時鍾函數 |
C5. 支持字符串處理的頭文件
頭文件 |
描 述 |
<string> |
為字符串類型提供支持和定義,包括單字節字符串(由char組成)的string和多字節字符串(由wchar_t組成) |
<cctype> |
單字節字符類別 |
<cwctype> |
多字節字符類別 |
<cstring> |
為處理非空字節序列和內存塊提供函數。這不同於對應的標准C庫頭文件,幾個C樣式字符串的一般C庫函數被返回值為const和非const的函數對替代了 |
<cwchar> |
為處理、執行I/O和轉換多字節字符序列提供函數,這不同於對應的標准C庫頭文件,幾個多字節C樣式字符串操作的一般C庫函數被返回值為const和非const的函數對替代了。 |
<cstdlib> |
為把單字節字符串轉換為數值、在多字節字符和多字節字符串之間轉換提供函數 |
C6. 定義容器類的模板的頭文件
頭文件 |
描 述 |
<vector> |
定義vector序列模板,這是一個大小可以重新設置的數組類型,比普通數組更安全、更靈活 |
<list> |
定義list序列模板,這是一個序列的鏈表,常常在任意位置插入和刪除元素 |
<deque> |
定義deque序列模板,支持在開始和結尾的高效插入和刪除操作 |
<queue> |
為隊列(先進先出)數據結構定義序列適配器queue和priority_queue |
<stack> |
為堆棧(后進先出)數據結構定義序列適配器stack |
<map> |
map是一個關聯容器類型,允許根據鍵值是唯一的,且按照升序存儲。multimap類似於map,但鍵不是唯一的。 |
<set> |
set是一個關聯容器類型,用於以升序方式存儲唯一值。multiset類似於set,但是值不必是唯一的。 |
<bitset> |
為固定長度的位序列定義bitset模板,它可以看作固定長度的緊湊型bool數組 |
C7. 支持迭代器的頭文件
頭文件 |
描 述 |
<iterator> |
給迭代器提供定義和支持 |
C8. 有關算法的頭文件
頭文件 |
描 述 |
<algorithm> |
提供一組基於算法的函數,包括置換、排序、合並和搜索 |
<cstdlib> |
聲明C標准庫函數bsearch()和qsort(),進行搜索和排序 |
<ciso646> |
允許在代碼中使用and代替&& |
C9. 有關數值操作的頭文件
頭文件 |
描 述 |
<complex> |
支持復雜數值的定義和操作 |
<valarray> |
支持數值矢量的操作 |
<numeric> |
在數值序列上定義一組一般數學操作,例如accumulate和inner_product |
<cmath> |
這是C數學庫,其中還附加了重載函數,以支持C++約定 |
<cstdlib> |
提供的函數可以提取整數的絕對值,對整數進行取余數操作 |
C10. 有關本地化的頭文件
頭文件 |
描 述 |
<locale> |
提供的本地化包括字符類別、排序序列以及貨幣和日期表示。 |
<clocale> |
對本地化提供C樣式支持 |
C++標准庫的所有頭文件都沒有擴展名。C++標准庫以<cname>形式的標准頭文件提供。在 <cname>形式標准的頭文件中,與宏相關的名稱在全局作用域中定義,其他名稱在std命名空間中聲明。在C++中還可以使用name.h形式的標准C庫頭文件名。
STL(Standard Template Library,標准模板庫)是惠普實驗室開發的一系列軟件的統稱。現然主要出現在C++中,但在被引入C++之前該技術就已經存在了很長的一段時間。
STL的代碼從廣義上講分為三類:algorithm(算法)、container(容器)和iterator(迭代器),幾乎所有的代碼都采用了模板類和模版函數的方式,這相比於傳統的由函數和類組成的庫來說提供了更好的代碼重用機會。在C++標准中,STL被組織為下面的13個頭文件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack>和<utility>。
1、算法
函數庫對數據類型的選擇對其可重用性起着至關重要的作用。舉例來說,一個求方根的函數,在使用浮點數作為其參數類型的情況下的可重用性肯定比使用整型作為它的參數類性要高。而C++通過模板的機制允許推遲對某些類型的選擇,直到真正想使用模板或者說對模板進行特化的時候,STL就利用了這一點提供了相當多的有用算法。它是在一個有效的框架中完成這些算法的——可以將所有的類型划分為少數的幾類,然后就可以在模版的參數中使用一種類型替換掉同一種類中的其他類型。
STL提供了大約100個實現算法的模版函數,比如算法for_each將為指定序列中的每一個元素調用指定的函數,stable_sort以你所指定的規則對序列進行穩定性排序等等。這樣一來,只要熟悉了STL之后,許多代碼可以被大大的化簡,只需要通過調用一兩個算法模板,就可以完成所需要的功能並大大地提升效率。
算法部分主要由頭文件<algorithm>,<numeric>和<functional>組成。<algorithm>是所有STL頭文件中最大的一個(盡管它很好理解),它是由一大堆模版函數組成的,可以認為每個函數在很大程度上都是獨立的,其中常用到的功能范圍涉及到比較、交換、查找、遍歷操作、復制、修改、移除、反轉、排序、合並等等。<numeric>體積很小,只包括幾個在序列上面進行簡單數學運算的模板函數,包括加法和乘法在序列上的一些操作。<functional>中則定義了一些模板類,用以聲明函數對象。
2、容器
在實際的開發過程中,數據結構本身的重要性不會遜於操作於數據結構的算法的重要性,當程序中存在着對時間要求很高的部分時,數據結構的選擇就顯得更加重要。
經典的數據結構數量有限,但是我們常常重復着一些為了實現向量、鏈表等結構而編寫的代碼,這些代碼都十分相似,只是為了適應不同數據的變化而在細節上有所出入。STL容器就為我們提供了這樣的方便,它允許我們重復利用已有的實現構造自己的特定類型下的數據結構,通過設置一些模版類,STL容器對最常用的數據結構提供了支持,這些模板的參數允許我們指定容器中元素的數據類型,可以將我們許多重復而乏味的工作簡化。
容器部分主要由頭文件<vector>,<list>,<deque>,<set>,<map>,<stack>和<queue>組成。對於常用的一些容器和容器適配器(可以看作由其它容器實現的容器),可以通過下表總結一下它們和相應頭文件的對應關系。
數據結構 |
描述 |
實現頭文件 |
向量(vector) |
連續存儲的元素 |
<vector> |
列表(list) |
由節點組成的雙向鏈表,每個結點包含着一個元素 |
<list> |
雙隊列(deque) |
連續存儲的指向不同元素的指針所組成的數組 |
<deque> |
集合(set) |
由節點組成的紅黑樹,每個節點都包含着一個元素,節點之間以某種作用於元素對的謂詞排列,沒有兩個不同的元素能夠擁有相同的次序 |
<set> |
多重集合(multiset) |
允許存在兩個次序相等的元素的集合 |
<set> |
棧(stack) |
后進先出的值的排列 |
<stack> |
隊列(queue) |
先進先出的執的排列 |
<queue> |
優先隊列(priority_queue) |
元素的次序是由作用於所存儲的值對上的某種謂詞決定的的一種隊列 |
<queue> |
映射(map) |
由{鍵,值}對組成的集合,以某種作用於鍵對上的謂詞排列 |
<map> |
多重映射(multimap) |
允許鍵對有相等的次序的映射 |
<map> |
3、迭代器
迭代器從作用上來說是最基本的部分,可是理解起來比前兩者都要費力一些。軟件設計有一個基本原則,所有的問題都可以通過引進一個間接層來簡化,這種簡化在STL中就是用迭代器來完成的。概括來說,迭代器在STL中用來將算法和容器聯系起來,起着一種黏和劑的作用。幾乎STL提供的所有算法都是通過迭代器存取元素序列進行工作的,每一個容器都定義了其本身所專有的迭代器,用以存取容器中的元素。
迭代器部分主要由頭文件<utility>,<iterator>和<memory>組成。<utility>是一個很小的頭文件,它包括了貫穿使用在STL中的幾個模板的聲明,<iterator>中提供了迭代器使用的許多方法,而對於<memory>的描述則十分的困難,它以不同尋常的方式為容器中的元素分配存儲空間,同時也為某些算法執行期間產生的臨時對象提供機制,<memory>中的主要部分是模板類allocator,它負責產生所有容器中的默認分配器。
三、后記
對於STL的使用,也普遍存在着兩種觀點。第一種認為STL的最大作用在於充當經典的數據結構和算法教材,因為它的源代碼涉及了許多具體實現方面的問題。第二種則認為STL的初衷乃是為了簡化設計,避免重復勞動,提高編程效率,因此應該是“應用至上”的,對於源代碼則不必深究。對於初學者而言,通過分析源代碼,提高對其應用的理解其意義也不同凡響。
曾經想着設計幾個上機題目,讓同學們體會一下利用STL編程。寫出一個適合初學者的,規模又不能太大,還要有足夠引導的題目,實在是一件非常費時費力的事,加上有其他事還得應急,就將此帳欠下,日后再說。要給同學們提的建議是,不少C++的經典教材對STL都有非常好的講解,可以選一本去讀。在讀書時,要開始學着挑着讀,跳着讀,不必從頭到尾,逐頁去讀。在這個階段,可以首先學習迭代器utility、在C++編程中建議替代數組的vector,以及實現雙向鏈表的list。vector和list與本周任務1和任務2似乎有些相關。再者,發揚我們一貫特別能實踐的精神,及時找些題目或者自編題目進行實踐。