C++ Primer(順序容器 上)
第九章 順序容器
標準庫定義了三種順序容器型別:vector、list 和 deque。
標準庫還提供了三種容器介面卡(adaptors): stack, queue, priority_queue
9.1順序容器的定義:#include <vector>
vector<string> svec;
#include <list>
list<int> ilist;
#include <deque>
deque<Sales_item> items;
9.1.1容器元素的初始化
表9-2 容器建構函式 |
|
C<T> c; |
建立一個名為c的空容器。C是容器型別名,如vector,T是元素型別,如int或string。 適用於所有容器 |
C c(c2); |
建立容器c2的副本c;c和c2必須具有相同的容器型別,並存放相同的元素。適用於所有容器 |
C c(b, e); |
建立c,其元素是迭代器b和e標示的範圍內元素的副本。適用於所有容器 |
C c(n, t); |
用n個值為t的元素建立容器c,其中值t必須是容器型別C的元素型別的值,或者是可轉換為該型別的值 只適用於順序容器 |
C c(n); |
穿件有n個值初始化 只適用於順序容器 |
1.將一個容器初始化為另一個容器的副本
容器型別混合元素型別相匹配
vector<int> ivec; //定義一個空的vector<int>型別,
vector<int> ivec2(ivec); //複製初始化
vector ivec2(ivec); // 同上
vector<int> ivec(10); // 十個零
vector<int>ivec(10,1); //十個一
2.初始化為一段元素的副本
vector<int> ivec(vec.begin(),vec.end()) //用兩個迭代器複製初始化
3.分配和初始化指定數目的元素
const list<int>::size_type list_size=64;
list<string> slist(list_size,"ee"); //64個字串,每個都是ee
9.1.2 容器內元素的型別約束容器內的元素型別必須是 1)支援賦值運算,2)支援複製
除了引用型別外,所有內建和複合型別都可以做元素型別。
容器的容器
vector< vector<int> .> lines; // attention!!!!這裡> .> 之間必須有空格!!
9.2迭代器和迭代器範圍
所有標準庫容器都支援*iter,iter->mem,++iter,iter++,--iter,iter--,iter1==iter2,iter1!=iter2
vector和deque提供了額外的運算!!如iter+n,iter-n,iter1+=iter2,>,<,>=,<=等.
list容器的迭代器既不支援算術運算(加法或減法),也不支援關係運算(<=,<,>=,>),只提供前置或後置的自增,自減運算及相等(不等)運算。
9.2.1迭代器範圍
C++ 語言使用一對迭代器標記迭代器範圍(iterator range),這兩個迭代器分別指向同一個容器中的兩個元素或超出末端的下一位置,通常將它們命名為
first 和 last,或 beg 和 end,用於標記容器中的一段元素範圍。
此類元素範圍稱為左閉合區間(left-inclusive interval),其標準表示方式為: [ first, last )
迭代器first和last形成一個迭代器範圍需滿足一下條件:它們指向同一個容器中的兩個元素或超出末端的下一位置;last絕對不能位於first之前。9.2.2使迭代器失效的容器操作
使用迭代器的時候,一定要注意那些操作可以使迭代器失效!!只要有元素的新增和刪除,begin或者end的結果會失效!!最好載重新定值。
在容器中新增元素,在容器中刪除元素,設定容器大小,獲取容器的第一個和最後一個元素
9.3.1容器定義的類型別名
表9-5 容器定義的類型別名 |
|
size_type |
無符號整型,足以儲存此容器型別的最大可能容器長度 |
iterator |
此容器型別的迭代器型別 |
const_iterator |
元素的只讀迭代器型別 |
reverse_iterator |
按逆序定址元素的迭代器 |
const_reverse_iterator |
元素的只讀(不能寫)逆序迭代器 |
difference_type |
足夠儲存兩個迭代器差值的有符號整型,可為負數 |
value_type |
元素型別 |
reference |
元素的左值型別,是value_type&的同義詞 |
const_reference |
元素的常量左值型別,等效於const value_type& |
返回一個迭代器c.begin() c.end()
返回一個逆序迭代器 c.rbegin() c.rend()
容器是const,返回型別要加上const_字首
9.3.3 在容器中新增元素
表9-7 在順序容器中新增元素的操作 |
|
c.push_back(t) |
在容器c的尾部新增值為t的元素。返回void型別 |
c.push_front(t) |
在容器c的前端新增值為t的元素。返回void型別 只適用於list和deque容器型別 |
c.insert(p,t) |
在迭代器p所指向的元素前面插入值為t的新元素。返回指向新新增元素的迭代器。 |
c.insert(p, n, t) |
在迭代器p所指向的元素前面插入n個值為t的新元素。返回void型別 |
c.insert(p, b, e) |
在迭代器p所指向的元素前面插入由迭代器b和e標記的範圍內的元素。返回void型別 |
新元素的插入在迭代器指向的位置之前
list<string> lst;
list<string>::iterator iter=lst.begin();
while(cin>>word)
iter=lst.insert(iter,wrod);// 同push_front功能相同
2.不要儲存end操作返回的迭代器,可以在每次做完插入運算後重新計算end迭代器值:
while(first!=v.end()){
first=v.insert(first,42);
++first;
}
9.3.4關係操作符
兩個容器可以大小比較,其實是其元素在作比較,如果元素不支援,則容器也不支援
ivec1 < ivec2
要求完全匹配,即容器型別與元素型別都相同,且元素型別支援<操作
9.3.5容器大小的操作
表9-8 順序容器的大小操作 |
|
c.size() |
返回容器c中的元素個數。返回型別為c::size_type |
c.max_size() |
返回容器c可容納的最多元素個數。返回型別為c::size_type |
c.empty() |
返回標記容器大小是否為0的布林值 |
c.resize(n) |
調整容器c的長度大小,使其能容納n個元素 如果n<c.size(), 則刪除多出來的元素; 否則,新增採用值初始化的新元素 |
c.resize(n, t) |
調整容器c的大小,使其能容納n個元素。所有新新增的元素之都為t |
表9-9 訪問順序容器內元素的操作 |
|
c.back() |
返回容器c的最後一個元素的引用。如果c為空,則該操作未定義 |
c.front() |
返回容器c的第一個元素的引用。如果c為空,則該操作未定義 |
c[n] |
返回下標為n的元素的引用 如果n<0或n>=c.size(),則該操作未定義 只適用於vector和deque容器 |
c.at(n) |
返回下表為n的元素的引用。如果下標越界,則該操作未定義 只適用於vector和deque容器 |
表9-10 刪除順序容器內元素的操作 |
|
c.erase(p) |
刪除迭代器p所指向的元素 返回一個迭代器,它指向被刪除元素後面的元素。如果p指向容器內的最後一個元素,則返回的迭代器指向容器的超出末端的下一位置。如果p本身就是指向超出末端的下一位置的迭代器,則該函式未定義 |
c.erase(b, e) |
刪除迭代器b和e所標記的範圍內的所有元素 返回一個迭代器,它指向被刪除元素段後面的元素。如果e本身就是指向超出末端的下一位置的迭代器,則返回的迭代器也指向容器的超出末端的下一位置 |
c.clear() |
刪除容器c內的所有元素。返回void |
c.pop_back() |
刪除容器c的最後一個元素。返回void。如果c為空容器,則該函式未定義 |
c.pop_front() |
刪除容器c的第一個元素。返回void。如果c為空容器,則該函式未定義。只適用於list和deque容器 |
vector容器型別不支援pop_front操作。
pop_front操作通常與front操作配套使用
while(!ilist.empty()){
process(ilist.front());
ilist.pop_front();
}//使用front獲取要處理的元素,使用pop_front從容器list刪除該元素。
2.刪除一個元素
必須在容器中找到要刪除的元素後,才能使用erase操作,且必須保證迭代器不是end迭代器
string searchValue("quasimodo");
list<string>::iterator iter=find(slist.begin(),slist.end(),searchValue);
if(iter!=slist.end())
slist.erase(iter);
9.3.8賦值與swap
表9-11 順序容器的賦值操作 |
|
c1 = c2 |
刪除容器c1的所有元素,然後將c2的元素複製給c1。c1和c2的型別(包括容器型別和元素型別)必須相同 |
c1.swap(c2) |
交換內容:呼叫完該函式後,c1中存放的是c2原來的元素,c2中存放的則是c1原來的元素。c1和c2的型別必須相同。該函式的執行速度通常要比將c2的元素複製到c1的操作快 |
c.assign(b, e) |
重新設定c的元素:將迭代器b和e標記的範圍內所有的元素複製到c中。b和e必須不是指向c中元素的迭代器 |
c.assign(n, t) |
將容器c重新設定為儲存n個值為t的元素 |
assign首先刪除容器中的所有元素,然後將其引數所指定的新元素插入到該容器中。兩個容器型別相同,元素型別相同,可以使用賦值操作符(=)。
在不同(或相同)型別的容器內,元素型別不同但是相互相容,賦值運算必須使用assign函式。
2.使用swap操作節省刪除元素的成本
要交換的容器型別匹配,運算元必須是相同型別的容器,而且所儲存的元素型別也必須相同。
9.4vector容器的自增長
vector提供兩個成員函式:capacity和reserve。capacity操作獲取容器需要分配更多的儲存空間之前能夠儲存的元素總數,reserve操作則告訴vector容器應該預留多少個元素的儲存空間。
size指的是容器當前擁有的元素個數。
9.5容器的選用
list容器可以高效的insert和erase一個元素且不需要移動任何其他元素,但不支援隨機訪問。
vector在除尾部的其他任何位置插入或刪除操作都要移動這個元素右邊的所有元素。
deque容器在兩端插入和刪除快,在中間操作代價高。
通常vector是隨機訪問的最佳選擇。