1 STL組建(STL Components)
關鍵組建:容器枷餐,迭代器残黑,算法
STL的基本觀念就是將數(shù)據(jù)和操作分離,數(shù)據(jù)由容器類加以管理晃危,操作則由可定制的算法定義之叙赚,迭代器在兩者之間充當粘合劑,使任何算法都可以和任何容器交互運作
2 容器(Containers)和迭代器
迭代器的分類:
1 雙向迭代器:
可以雙向進行僚饭,以遞增運算前進或以遞減運算符后退(list set multiset map multimap 均提供此類迭代器)
2隨機存期迭代器:
隨機存取迭代器具備雙向迭代器的所有有屬性還具備隨機訪問能力:vector deque string
3之間差異:
For(pos=coll.begin();pos!=coll.end();++pos) { ………………… } For(pos=coll.begin();pos<coll.end();++pos) ………
只有隨機訪問迭代器才支持operation<<; 所以代碼一般會寫成第一種
容器相關函數(shù):
reverse()將區(qū)間能元素翻轉
coll2.resize(coll.size());//改變coll2元素個數(shù)
deque<int>coll3(coll1.size());初始化時指明要有的足夠空間
六迭代器之配接器:
(一)三種迭代器配接器:
1 Insert iterators(安插型迭代器)
2stream iterators(流迭代器)
3Reverse iterators(逆向迭代器)
安插型迭代器:
Inset iterators 可以使算法以安插的方式而非覆寫方式運作可以解決算法的“目標空間不足”的問題是的它會促使目標區(qū)間的大小按需要成長
如果對某個元素設值會引發(fā)所屬群集的安插操作震叮,至于插入位置在容器的最前還是最后或是某個指定位置上,需要視三種情況而定:
(1) 單步前進不造成任何動靜
1.1 Back inserters(安插于容器最尾端)
Back inseters 內部調用push_back()在容器尾端插入元素
Copy(coll1.begin(),coll1.end(),back_inserter(coll2)
(只有vector deque list提供push_back())
2.2 Front Inserters(安插于容器最前端)
Copy(coll1.begin(),coll1.end(),front_inserter(coll3));
這種動作逆轉了被安插元素的次序如果先安插1再向前安插2那么1會在2后邊提供push_front的容器只有:deque list
2.3 Generalinerters(一般性安插器):
一般性的inserters它的作用是將元素插入初始化時接受第二個參數(shù)的位置的前方inserters 內部調用成員函數(shù)insert()并以新值和新位置做參數(shù)所有STL容器都提供insert()函數(shù)
(2)Stream Iterator(流迭代器)
copy(istream_iterator<string>(cin),istream_iterator<string>(),back_inserter(coll));
sort(coll.begin(),coll.end());
unique_copy(coll.begin(),coll.end(),ostream_iterator<string>(cout,"\n"));
2.1istream_iterator<string>(cin)
這個產(chǎn)生一個可從標準輸入流cin讀取數(shù)據(jù)的streamiterator
2.2 istream_iterator<string>()
調用istreamiterator 的default構造函數(shù)產(chǎn)生一個代表”流結束”符號的迭代器它表示你不能在從中讀取任何東西
2.3 ostream_iterator<string>(cout,”\n”)
產(chǎn)生一個output stream iterator浪慌,透過operator<<向cout寫入strings第二個參數(shù)作為元素之間分割符
(2) Reverse Iterator(逆向迭代器)
逆向方式進行操作
所有容器都可以通過成員函數(shù)rbegin()和rend()產(chǎn)生出reverse iterator
(二)更易型算法(manipulatingalgorithm刪除或重排或修改元素的算法)
1 算法remove()自某個區(qū)間刪除元素
for(inti=1;i<=6;++i)
{
coll.push_front(i);
coll.push_back(i);
}
remove(coll.begin(),coll.end(),3);
結果:654211245656
數(shù)值為3刪除后被其后元素覆蓋冤荆,至于群集尾端那些違背覆蓋的元素朴则,原封不動但從邏輯上說权纤,那些元素已經(jīng)不屬于這個群集了
改進:
List<int>::iterator end=remove(coll.begin(),coll.end(),3)
copy(coll.begin()end,ostream_iterator<int>(cout,","));
結果:6542112456
或者采用:
Distance(end,coll.end());
Distance()是返回兩個迭代器之間的距離
如果真想把刪除的元素斬草除根你必須調用該容器的相應成員函數(shù)容器提供成員函數(shù)erase()適用此目的erase()可以刪除“參數(shù)所指示區(qū)間”內的全部元素
2更易型算法和相關容器
Erase()成員函數(shù)返回刪除元素的個數(shù)
(三)以函數(shù)作為算法的參數(shù)
void print(intelem)
{
cout<<elem<<" ";
}
for_each(coll.begin(),coll.end(),print);
2判斷式(predicate)
所謂predicate就是返回布爾值的函數(shù)他們通常用來指定排序規(guī)則和搜索準則,并非任何返回bool值得一元函數(shù)或二元函數(shù)就是合法的predicate STL要求面對相同的值predicate必須得出相同的結果乌妒,這條戒律將那些“被調用時會改變自己內部狀態(tài)的函數(shù)排除了”
3仿函數(shù)(functors,FunctionObject即函數(shù)對象)
傳遞給算法的“函數(shù)參數(shù)”不一定是函數(shù)汹想,可以是行為類似函數(shù)的對象
仿函數(shù)的優(yōu)點:
(1) 智能型含糊 smart point
仿函數(shù)可擁有成員函數(shù)和成員變量這意味著仿函數(shù)擁有狀態(tài),其次你可以在初始時初始化他們撤蚊,當然必須在他們被調用之前
(2) 仿函數(shù)都有自己的型別(可以設計函數(shù)繼承體系)
(3) 仿函數(shù)比一般函數(shù)要快
預定義的仿函數(shù):
Set<int>coll;會被擴展為set<int,less<int>>coll;
所以反向排列這些元素可以是set<int,greater<int>>coll;
透過一些特殊函數(shù)配接器你可以將預定義的仿函數(shù)和其它數(shù)值組合到一起或使用特殊狀況
例如:
Transform(coll.begin(),coll.end(),back_inserter(coll2),bind2d(mltiiplies<int>(),10)
將coll中的所有元素乘以10后安插到coll2中這里使用配接器使得multiple<int>運算時以源群集的元素作為第一個參數(shù)古掏,10作為第二個參數(shù)
仿函數(shù)一般聲明為:inline
特殊仿函數(shù):
For_each(coll.begin(),coll.end(),mem_fun_ref(&Person::save());
仿函數(shù)mem_fun_ref用來調用他所作用的元素的某個成員函數(shù)
(四)容器內的元素
1 容器元素的條件
(1)必須可以通過copy構造函數(shù)進行復制,copy函數(shù)的性能盡可能優(yōu)化
(2)必須可以透過assignment操作符完成賦值操作(即=號)
(3)必須可以通過析構函數(shù)完成銷毀動作析構函數(shù)決不能設計成preivate
析構函數(shù)決不能拋出異常
(4) 對于序列式容器而言侦啸,元素的default構造函數(shù)必須可用
(5) 對于某些動作必須定義operatpor==以執(zhí)行相等測試
(6)在關聯(lián)式容器中元素必須定義排序準則缺省情況下operator<透過仿函數(shù)less<>調用