提供了類型安全、高效而易用特性的STL無疑是最值得C++程序員驕傲的部分。每一個C++程序員都應該好好學習STL:).
STL(Standard Template Library 標准模板庫)是C++標准庫的一個重要組成部分,它由Stepanov and Lee等人最先開發,它是與C++幾乎同時開始開發的;一開始STL選擇了Ada作為實現語言,但Ada有點不爭氣,最後他們選擇了C++,一個原因了,C++中已經有了模板。在後來,STL又被添加進了C++庫。1996年,惠普公司又免費公開了STL,為STL的推廣做了很大的貢獻。
STL大體上包括container(容器)、algorithm(算法)和iterator(迭代器),容器和算法通過迭代器可以進行無縫連接。
STL體現了范型編程的思想,它具有高度的可重用性,高性能,高移植性。程序員不用思考具體實現過程,只要能夠熟練的應用就OK了。(有興趣研究具體實現的,可以看侯捷老師編著的《STL源碼剖析》)這樣他們就可以把精力放在程序開發的別的方面。
我非常佩服創造STL的那些計算機和數學精英。因為他們做了一件非常辛苦的事情―――抽象概念。而STL就是通過把容器抽象為統一的接口,算法利用這個接口,通過迭代器來操縱容器。因為接口不變,實現的容器可以隨意更改。這樣,就為編程、調試和擴展提供了便利。也許有一天,我們生產軟件的時候也可以想DIY一台PC一樣簡單,只要拿來相應的實現模塊,通過簡單的拼裝和調試就可以創造一個軟件。這是多麼令人興奮的一件事^_^.不過,到時候,可能會有很多程序員失業了。呵呵,畢竟編寫類庫不需要很多的人員。
雖然STL不是面向對象的,但,我想,每個人都會為它的創造力和高性能而感到興奮和折服。
一、容器
作為STL的最主要組成部分--容器,分為向量(vector),雙端隊列(deque),表(list),隊列(queue),堆棧(stack),集合(set),多重集合(multiset),映射(map),多重映射(multimap)。
容器 特性 所在頭文件 向量vector 可以用常數時間訪問和修改任意元素,在序列尾部進行插入和刪除時,具有常數時間復雜度,對任意項的插入和刪除就有的時間復雜度與到末尾的距離成正比,尤其對向量頭的添加和刪除的代價是驚人的高的 <vector> 雙端隊列deque 基本上與向量相同,唯一的不同是,其在序列頭部插入和刪除操作也具有常量時間復雜度 <deque> 表list 對任意元素的訪問與對兩端的距離成正比,但對某個位置上插入和刪除一個項的花費為常數時間。 <list> 隊列queue 插入只可以在尾部進行,刪除、檢索和修改只允許從頭部進行。按照先進先出的原則。 <queue> 堆棧stack 堆棧是項的有限序列,並滿足序列中被刪除、檢索和修改的項只能是最近插入序列的項。即按照後進先出的原則 <stack> 集合set 由節點組成的紅黑樹,每個節點都包含著一個元素,節點之間以某種作用於元素對的謂詞排列,沒有兩個不同的元素能夠擁有相同的次序,具有快速查找的功能。但是它是以犧牲插入車刪除操作的效率為代價的 <set> 多重集合multiset 和集合基本相同,但可以支持重復元素具有快速查找能力 <set> 映射map 由{鍵,值}對組成的集合,以某種作用於鍵對上的謂詞排列。具有快速查找能力 <map> 多重集合multimap 比起映射,一個鍵可以對應多了值。具有快速查找能力 <map>
考慮到不同的實際需要,更主要的是效率的需要,我們可以選擇不同的容器來實現我們的程序,以此達到我們提高性能的目的。這也是用好STL的一個難點,但這也是關鍵。
二、算法
算法部分主要由頭文件<algorithm>,<numeric>和<functional>組成。<algorithm>是所有STL頭文件中最大的一個,它是由一大堆模版函數組成的,可以認為每個函數在很大程度上都是獨立的,其中常用到的功能范圍涉及到比較、交換、查找、遍歷操作、復制、修改、移除、反轉、排序、合並等等。<numeric>體積很小,只包括幾個在序列上面進行簡單數學運算的模板函數,包括加法和乘法在序列上的一些操作。<functional>中則定義了一些模板類,用以聲明函數對象。
STL的算法也是非常優秀的,它們大部分都是類屬的,基本上都用到了C++的模板來實現,這樣,很多相似的函數就不用自己寫了,只要用函數模板就OK了。
我們使用算法的時候,要針對不同的容器,比如:對集合的查找,最好不要用通用函數find(),它對集合使用的時候,性能非常的差,最好用集合自帶的find()函數,它針對了集合進行了優化,性能非常的高。
三、迭代器
它的具體實現在<itertator> 中,我們完全可以不管迭代器類是怎麼實現的,大多數的時候,把它理解為指針是沒有問題的(指針是迭代器的一個特例,它也屬於迭代器),但是,決不能完全這麼做。
迭代器功能(Abilities Of Iterator Gategories)
輸入迭代器
Input iterator
向前讀
Reads forward
istream
輸出迭代器
Output iterator
向前寫
Writes forward
ostream,inserter
前向迭代器
Forward iterator
向前讀寫
Read and Writes forward
雙向迭代器
Bidirectional iterator
向前向後讀寫
Read and Writes forward and
backward
list,set,multiset,map,mul
timap
隨機迭代器
Random access iterator
隨機讀寫
Read and Write with random
access
vector,deque,array,string
由此可見,指針和迭代器還是有很大差別的。和指針最接近的就是隨機訪問迭代器。下面是一個我編寫的小例子:功能是分別對數組,向量,表,多重集合進行插入操作,對每個容器插入100萬個隨機整數;
#include<iostream>
#include<iterator>
#include<vector>
#include<list>
#include<set>
#include<time.h>
#include<conio.h>
#include<algorithm>
using namespace std;
template<typename T>
void arrayInsert(T*a,T*s,long size) //向數組插入數據
{
//for(long i=0;i<10;i++) // //好像數組支持不到100萬,我們就算10萬的
//最後在把把結果乘以10吧,
//{
for(long k=0;k<size;k++)
{
a[k]=s[k];
}
/