順序容器只定義了很少的操作,我們希望容器支援更多的操作。c++標準庫為了滿足更多開發者的需求,實現了一些經典演算法的公共介面,因為這些演算法不依賴於具體的容器,而是借助迭代器對容器進行操作,所以常稱其為泛型演算法。
泛型演算法都定義在標頭檔案中,少數數值型演算法定義在
標頭檔案中。
一般情況下,演算法不會直接操作容器,而是借助容器的迭代器來遍歷、操作容器中的元素。而且,大多數演算法絕對不會改變容器的長度。(erase和insert等操作不是演算法,而是「容器操作」,注意分清)
唯讀演算法會讀取輸入範圍內的元素,而絕對不會改變元素,這種情況下我們一般使用常量迭代器。
if (it != intvec.cend())
cout << *it
<< endl;
find查詢容器中是否存在值為value的元素,如果不存在返回尾後迭代器。
auto sum = accumulate(intvec.cbegin(), intvec.cend(), 0);
accumulate定義在
標頭檔案中,用來求容器中一段範圍的和,第三個引數是sum的初始值,注意初始值的選取和容器中元素的型別是有關係的。如果是double型要初始化為0.0.
值得一提的是,accumulate並不支援所有的元素型別。
元素型別必須定義了「+」操作才可以用accumulate。
例如:
vector
vec =;
auto sum = accumulate(vec.cbegin(),vec.cend()," ");
因為char*並不支援『+』操作,所以編譯器報錯,如果是vector
是可以的。
equal(c1.cbegin(), c1.cend(), c2.cbegin());
該演算法接收三個迭代器。前兩個迭代器表示第乙個序列的範圍,第三個迭代器是第二個序列的起始迭代器位置。這個演算法基於這樣的程式設計假設:
1.c1和c2容器型別不必相同,但是容器中的元素型別必須相同
2.容器中的元素型別必須支援「==」操作。(例如某些自定義類可能沒有過載「==」運算子,那麼就不能用該演算法)
3.第二個序列的長度至少和第乙個序列的長度相同
前邊曾經提到過,絕大部分演算法不會修改容器的長度,這好像限制了某些操作。
例如:
vector
intvec;//空容器
fill_n(intvec.begin(), 10, 0);
這裡執行會報錯。因為規定演算法不可以修改容器的長度,此時容器長度為0。這一點很容易出現致命錯誤,因為編譯器不會檢查演算法的寫操作是否合法,需要程式設計師保證。
我們可以先分配給intvec一些空間後,再指向fill_n操作。
intvec.resize(20);
fill_n(intvec.begin(), 10, 0);
注意這裡是resize而不是reserve。vector 的reserve增加了vector的capacity,但是它的size沒有改變!而resize改變了vector的capacity同時也增加了它的size!
除了剛才的方法,還可以用一種叫做」插入迭代器」的方式來得到我們期望的結果。
插入迭代器back_inserter
是一種」迭代器介面卡「。
介面卡是一種介面轉換器,它可以讓一種東西看起來像另一種東西。
在這裡back_inserter
使得迭代器能夠像函式push_back
進行一樣的操作,它使得乙個迭代器看起來像是呼叫了push_back
一樣。
fill_n(back_inserter(intvec), 10, 0);//新增10個0到intvec中去
這裡在提醒一下,我們之前說過演算法不可以改變容器的size,那這裡為什麼可以成功執行不出錯呢?
原因在於,演算法操作了乙個迭代器,迭代器可以完成向容器中新增元素的功能,但是演算法本身永遠不會這麼做,所以和我們之前說的並不矛盾。
auto it1 = back_inserter(intvec);//插入器繫結到了intvec上並且生成了乙個迭代器it
*it1 = 10;//相當於intvec.push_back(10)
除了back_inserter
之外還有front_inserter
(呼叫push_front
)和inserter
呼叫容器操作的inserter
。
例如:auto it3 = inserter(intvec, intvec.begin())
在intvec.begin()位置之前呼叫insert()
容器操作。
當然,vector
並不可以使用front_inserter()
,因為vector
上沒有定義push_front
操作。
vector
l;copy(intvec.cbegin(), intvec.cend(), l.begin());
l是空容器,l.size() == 0,copy不可以改變其size所以操作出錯。可以預先改變l的size或者利用back_inserter
改變l的size:
vector
l;l.resize(100);
copy(intvec.cbegin(), intvec.cend(), l.begin());
利用back_inserter
vector
l;copy(intvec.cbegin(), intvec.cend(), back_inserter(l));
replace(l.begin(), l.end(), 0, 101);
將l的所有0替換為101. C 泛型基礎
泛型的基本思想 泛型程式設計 generic programming 是一種語言機制,通過它可以實現乙個標準的容器庫。像類一樣,泛型也是一種抽象資料型別,但是泛型不屬於物件導向,它是物件導向的補充和發展。在物件導向程式設計中,當演算法與資料型別有關時,物件導向在對演算法的抽象描述方面存在一些缺陷。比...
基礎 C 泛型
msdn 章節內容 ms help 泛型是 2.0 版 c 語言和公共語言執行庫 clr 中的乙個新功能。泛型將型別引數的概念引入 net framework,型別引數使得設計如下類和方法成為可能 這些類和方法將乙個或多個型別的指定推遲到客戶端 宣告並例項化該類或方法的時候。例如,通過使用泛型型別引...
C 泛型基礎
泛型的基本思想 泛型程式設計 generic programming 是一種語言機制,通過它可以實現乙個標準的容器庫。像類一樣,泛型也是一種抽象資料型別,但是泛型不屬於物件導向,它是物件導向的補充和發展。在物件導向程式設計中,當演算法與資料型別有關時,物件導向在對演算法的抽象描述方面存在一些缺陷。比...