1. 程式人生 > >C++ STL庫/C標頭檔案函式

C++ STL庫/C標頭檔案函式

轉載@Memset  轉載@Jason333

目錄

List                               操作函式

優先佇列

Vector

1、結構

  vector模塑出一個動態陣列,因此,它本身是“將元素置於動態陣列中加以管理”的一個抽象概念。vector將其元素複製到內部的dynamic array中。元素之間總存在某種順序,所以vector是一種有序群集。vector支援隨機存取,因此只要知道位置,可以在常數時間記憶體取任何一個元素。根據vector的結構可知,在末端新增或者刪除元素,效能相當好,如果在前端或者中部安插或刪除元素,效能就不怎麼樣了,因為操作點之後的元素都需要移到另一位置,而每一次移動都需要呼叫assignement(賦值)操作符。

2、大小(size)和容量(capacity)

2.1 效能 

  vector的優異效能的祕訣之一就是配置比其容納元素所需更多的記憶體。vector用於操作大小的函式有size(),empty(),max_size(),另一個有關大小的函式是capacity(),它返回的是vector實際能夠容納的元素數量,如果超越這個數量,vector就有必要重新配置內部儲存器。

  vector的容量之所以很重要,有以下兩個原因:

  • 一旦記憶體重新分配,和vector相關的所有元素都會失效,如:references,pointers,iterators。
  • 記憶體分配很耗時間

2.2 記憶體分配

2.2.1 reserve

  如果程式管理了和vector元素相關的reference,pointers,iterator,或者執行效率至關重要,那麼就必須考慮容器的容量問題。可以使用reserve()來保留適當容量,避免一再的分配記憶體,只要保留的容量有剩餘,就不用擔心reference失效。

std::vector<T> v;
v.reserve(n);   //為vector分配容量為n的記憶體

  還有一點要記住的是,如果呼叫reserve()所給的引數比當前的vector容量還小,不會發生任何反應,vector不能通過reverse來縮減容量。如何達到時間和空間的最佳效率,由系統版本決定,很多時候為了防止記憶體破碎,即使不呼叫reserve,當你第一次安插元素的時候,也會一次性配置整塊記憶體(例如2K)。vector的容量不會縮減,即使刪除元素,其reference,pointers,iterators也不會失效,繼續指向發生動作之前的位置,然而安插元素可能使這些元素失效(因為安插可能重新分配記憶體空間)。

2.2.2 構造分配

  另外一種避免重新分配記憶體的方法是,初始化期間就像建構函式傳遞附加引數,構造出足夠的空間。如果引數是個數值,它將成為vector的起始大小。

std::vector<T> v(500);  //分配能容納500個T元素的記憶體大小

   當然,要獲得這種能力,這種元素必須提供一個default建構函式,如果型別很複雜,提供了default建構函式,初始化也會很耗時,如果只是為了保留足夠的記憶體,建議使用reverse()。

2.2.3 記憶體縮減

  當然,要想縮減vector記憶體還是有方法的,那就是兩個vector交換了內容後,兩者的容量也會交換,即保留元素,又縮減了記憶體。

複製程式碼

template<class T>
void shrinkCapacity(std::vector<T> &v)
{
    std::vector<T> temp(v);  //初始化一個新的vector
    v.swap(temp);             //交換元素內容
}

複製程式碼

  或者通過下列語句:

std::vector<T> (v).swap(v);

  不過應該注意的是,swap()之後,原先所有的reference,pointers,iterator都換了指涉物件,他們仍然指向原本位置,也就是說它們在交換之後,都失效了。

複製程式碼

void mvTestSize()
    {
        // size 為20的vector
        vector<int> veciSize1;
        for (int i = 0; i < 20; i++)
        {
            veciSize1.push_back(i);
        }

        cout << "v1 size:" << veciSize1.size() << endl;
        cout << "v1 max size:" << veciSize1.max_size() << endl;
        cout << "v1 capacity:" << veciSize1.capacity() << endl;

        // size為200的vector
        vector<int> veciSize2;
        for (int i = 0; i < 200; i++)
        {
            veciSize2.push_back(i);
        }

        cout << "v2 size:" << veciSize2.size() << endl;
        cout << "v2 max size:" << veciSize2.max_size() << endl;
        cout << "v2 capacity:" << veciSize2.capacity() << endl;

        //分配固定的size
        vector<int> veciSize3;
        veciSize3.reserve(1000);
        for (int i = 0; i < 20; i++)
        {
            veciSize3.push_back(i);
        }

        cout << "v3 size:" << veciSize3.size() << endl;
        cout << "v3 max size:" << veciSize3.max_size() << endl;
        cout << "v3 capacity:" << veciSize3.capacity() << endl;
    }

複製程式碼

  輸出結果:

3、 vector操作函式

3.1 構造、拷貝和析構

  可以在構造時提供元素,也可以不提供。如果指定大小,系統會呼叫元素的default建構函式一一製造新元素。

操作

效果

vector<Elem> c

產生一個空的vector,沒有任何元素

vector<Elem> c1(c2)

產生另一同一型別的副本 (所有元素都被拷貝)

vector<Elem> c(n)

利用元素的default建構函式生成一個大小為n的vector

vector<Elem> c(n,elem)

產生一個大小為n的vector,每個元素都是elem

vector<Elem> c(beg,end)

產生一個vector,以區間[beg,end)作為初始值

c.~vector<Elem>()

銷燬所有元素,釋放記憶體

3.2 非變動操作

操作

效果

c.size()

返回當前的元素數量

c.empty()

判斷大小是否為零,等同於0 == size(),效率更高

c.max_size()

返回能容納的元素最大數量

capacity()

返回重新分配空間前所能容納的最大元素數量

reserve()

如果容量不足,擴大

c1 == c2

判斷c1是否等於c2

c1 != c2

判斷c1是否不等於c2(等同於!(c1==c2))

c1 < c2

判斷c1是否小於c2

c1 > c2

判斷c1是否大於c2

c1 <= c2

判斷c1是否小於等於c2(等同於!(c2<c1))

c1 >= c2

判斷c1是否大於等於c2 (等同於!(c1<c2))

3.3 賦值操作

操作

效果

c1 = c2

將c2的元素全部給c1

c.assign(n,elem)

複製n個elem給c

c.assign(beg,end)

將區間[beg,end)賦值給c

c1.swap(c2)

將c1和c2元素互換

swap(c1,c2)

將c1和c2元素互換,全域性函式

   值得注意的是,所有的賦值操作都可能呼叫元素的default建構函式,copy建構函式和assignment操作符或者解構函式。

3.4 元素存取

操作

效果

c.at(idx)

返回索引idx標示的元素,如果越界,丟擲越界異常

c[idx]

返回索引idx標示的元素,不進行範圍檢查

c.front()

返回第一個元素,不檢查第一個元素是否存在

c.back()

返回最後一個元素,不檢查最後一個元素是否存在

  按照c/c++的慣例,第一個元素的索引為0,所以n個元素的索引為n-1。只有at()會檢查範圍,其他函式不檢查範圍,如果越界,除了at()會丟擲異常,其他函式會引發未定義行為,所以使用索引的時候,必須確定索引有效,對一個空的vector使用front()和back()都會發生未定義行為,所以呼叫他們,必須保證vector不為空。

  對於non-const-vector,這些函式返回的都是reference,可以通過這些函式來改變元素內容。

3.5 迭代器相關函式

  vector提供了一些常規函式來獲取迭代器。vector的迭代器是random access iterators(隨機存取迭代器),簡單的來說就是陣列一樣的迭代器,可以直接使用下標操作。

操作

效果

c.begin()

返回一個隨機存取迭代器,指向第一個元素

c.end()

返回一個隨機存取迭代器,指向最後一個元素的下一個位置

c.rbegin()

返回一個逆向迭代器,指向逆向迭代的第一個元素

c.rend()

返回一個逆向迭代器,指向逆向迭代的最後一個元素的下一個位置

3.5.1迭代器失效條件

  • 使用者在較小位置安插或移除元素。
  • 由於容量變化而引起記憶體重新分配。

3.5.2 安插和移除元素

  vector提供安插和移除操作函式,呼叫這些函式,必須保證引數合法:

  • 迭代器必須指向一個合法位置。
  • 區間的起始位置不能在結束位置之後。
  • 不能從空容器中移除元素。

  關於效能,下列情況的安插和移除操作可能效率高一些:

  • 在容器的尾部安插或刪除元素。
  • 容量一開始就很大。
  • 安插多個元素,呼叫一次比呼叫多次快。

  安插和刪除元素,會使“作用點”之後的各元素的reference、pointers、iterators失效,如果安插操作導致記憶體重新分配,該容器的所有reference、pointers、iterators都會失效。

操作

效果

c.insert(pos,elem)

在pos位置上插入一個elem副本,並返回新元素位置

c.insert(pos,n,elem)

在pos位置插入n個elem副本,無返回值

c.insert(pos,beg,end)

在pos位置插入[beg,end]內所有元素的副本,無返回值

c.push_back(elem)

在尾部新增一個elme副本

c.pop_back()

移除最後一個元素

c.erase(pos)

移除pos上的位置,返回下一個元素的位置

c.erase(beg,end)

移除[beg,end)內的所有元素,並返回下一元素的位置

c.resize(num)

將元素的位置改為num個(如果size變大了,多出來的元素需要default建構函式來完成構造))

c.resize(num,elem)

將元素的位置改為num個(如果size變大了,多出來的元素都是elem的副本))

c.clear()

移除所有元素,將容器清空

List

1、結構

  list使用一個double linked list(雙向連結串列)來管理元素。

2、 list 能力

  list內部結構和vector或deque截然不同,所以與他們的區別:

  list不支援隨機存取,需要存取某個元素,需要遍歷之前所有的元素,是很緩慢的行為。

  任何位置上(不止是兩端)安插和刪除元素都非常快,始終都是在常數時間內完成,因為無需移動其他任何操作,實際上只進行了一些指標操作。

  安插和刪除並不會造成指向其他元素的各個pointers、reference、iterators失效

  list是原子操作,要麼成功,要麼失敗,不會說只執行一半。

  list不支援隨機存取,不提供下標操作符和at()函式。

  list不提供容量,記憶體分配的操作函式,因為完全沒必要,每個元素都有自己的記憶體空間,在刪除之前一直有效。

  list提供專門的函式用於移動函式,這些函式執行效率高,無需元素的拷貝和移動,只需要調整若干指標。

3、操作函式

3.1 構造和析構

操作

效果

list<Elem> c

產生一個空的list

list<Elem> c1(c2)

產生一個c2同型的list,每個元素都被複制

list<Elem> c(n)

產生一個n個元素的list,每個元素都由default構造產生

list<Elem> c(n,elem)

產生一個n個元素的list,每個元素都是elem的副本

list<Elem> c (beg,end)

產生一個list以區間[beg,end)內所有元素作為初值

c.~list<Elem>()

銷燬所有元素,釋放記憶體

3.2 非變動性操作

操作

效果

c.size()

返回當前的元素數量

c.empty()

判斷大小是否為零,等同於0 == size(),效率更高

c.max_size()

返回能容納的元素最大數量

c1 == c2

判斷c1是否等於c2

c1 != c2

判斷c1是否不等於c2(等同於!(c1==c2))

c1 < c2

判斷c1是否小於c2

c1 > c2

判斷c1是否大於c2

c1 <= c2

判斷c1是否小於等於c2(等同於!(c2<c1))

c1 >= c2

判斷c1是否大於等於c2 (等同於!(c1<c2))

3.3 賦值

操作

效果

c1 = c2

將c2的元素全部賦值給c1

c.assign(n,elem)

將elem的n個副本拷貝給c

c.assign(beg,end)

建立一個list,區間[beg,end)內的所有元素作為初值

c1.swap(c2)

c1和c2元素互換

swap(c1,c2)

c1和c2元素互換,全域性函式

3.3 元素存取

  list不支援隨機存取,只有front()和back()能直接存取元素。

操作

效果

c.front()

返回第一個元素,不檢查元素是否存在

c.back()

返回最後一個元素,不檢查元素是否存在

3.4 迭代器相關函式

  list只有使用迭代器才能對元素進行存取,list不支援隨機存取,所以這些迭代器是雙向迭代器,凡是用到隨機存取迭代器的演算法都不能使用。

操作

效果

c.begin()

返回一個隨機存取迭代器,指向第一個元素

c.end()

返回一個隨機存取迭代器,指向最後一個元素的下一個位置

c.rbegin()

返回一個逆向迭代器,指向逆向迭代的第一個元素

c.rend()

返回一個逆向迭代器,指向逆向迭代的最後一個元素的下一個位置

3.5 元素的安插和移除

  list提供了deque的所有功能,還增加了remove()和remove_if()應用於list。

操作

效果

c.insert(pos, elem)

在迭代器pos位置插入一個elem副本,返回新元素位置

c.insert(pos,n, elem)

在迭代器pos位置插入n個elem副本,無返回值

c.insert(pos, beg,end)

在迭代器pos位置插入區間[beg,end)內所有元素的副本,無返回值

c.push_back(elem)

在尾部追加一個elem副本

c.pop_back()

移除最後一個元素,不返回

c.push_front(elem)

在頭部安插一個elem副本

c.pop_front()

移除第一個元素,不返回

c.remove(val)

移除所有值為val的元素

c.remove_if(op)

移除所有“造成op(elem)為true”的元素

c.erase(pos)

移除迭代器pos所指元素,返回下一元素位置

c.erase(beg,end)

移除區間[beg,end)內的所有元素,返回下一元素位置

c.resize(num)

將元素容量重置為num個,如果size變大,則以default建構函式構造所有元素

c.resize (num, elem)

將元素容量重置為num個,如果size變大,則所有元素為elem的副本

c. clear ()

移除所有元素,將整個容器清空

3.6 特殊變動性操作

操作

效果

c.unique()

如果存在若干相鄰而數值相等的元素,移除重複元素,只留下一個

c.unique(op)

若存在若干相鄰元素,都使op()為true,移除重複元素,只留下一個

c1.splice(pos,c2)

將所有c2元素移到c1容器pos迭代器之前

c1.splice(pos,c2,c2pos)

將c2 pos位置元素移到c1元素pos位置,c1和c2可以相同

c1.splice(pos,c2,c2beg,c2end)

將c2區間[c2beg,c2end)所有元素移到c1 pos位置之前,c1和c2可以相同

c.sort()

以operator < 為準,對所有元素排序

c.sort(op)

以op()為準,對c排序

c1.merge(c2)

假設c1和c2已序,將c2元素移動到c1,並保證合併後的list仍為已序

c1.merge(c2,op)

假設c1和c2都以op()為序,將c2移動到c1仍然以op()已序

c.reverse()

將所有元素反序

 Set和Multiset

1、結構

  set和multiset會根據特定的排序原則將元素排序。兩者不同之處在於,multisets允許元素重複,而set不允許重複。

  只要是assignable、copyable、comparable(根據某個排序準則)的型別T,都可以成為set或者multisets的元素。如果沒有特別的排序原則,採用預設的less,已operator < 對元素進行比較,以便完成排序。

排序準則必須遵守以下原則:

  •  必須是“反對稱的”,對operator <而言,如果x < y為真,y<x為假。
  •  必須是“可傳遞的”,對operator <而言,如果x<y為真,y<z為真,那麼x<z也為真。
  •  必須是“非自反的”,對operator<而言,x<x永遠為假。

2、能力

  和所有的標準關聯容器類似,sets和multisets通常以平衡二叉樹完成。

  自動排序的主要優點在於使二叉樹搜尋元素具有良好的效能,在其搜尋函式演算法具有對數複雜度。但是自動排序也造成了一個限制,不能直接改變元素值,因為這樣會打亂原有的順序,要改變元素的值,必須先刪除舊元素,再插入新元素。所以sets和multisets具有以下特點:

  • 不提供直接用來存取元素的任何操作元素
  • 通過迭代器進行元素的存取。

3、操作函式

3.1 構造、拷貝、析構

操作

效果

set c

產生一個空的set/multiset,不含任何元素

set c(op)

以op為排序準則,產生一個空的set/multiset

set c1(c2)

產生某個set/multiset的副本,所有元素都被拷貝

set c(beg,end)

以區間[beg,end)內的所有元素產生一個set/multiset

set c(beg,end, op)

以op為排序準則,區間[beg,end)內的元素產生一個set/multiset

c.~set()

銷燬所有元素,釋放記憶體

set<Elem>

產生一個set,以(operator <)為排序準則

set<Elem,0p>

產生一個set,以op為排序準則

3.2 非變動性操作

操作

效果

c.size()

返回當前的元素數量

c.empty ()

判斷大小是否為零,等同於0 == size(),效率更高

c.max_size()

返回能容納的元素最大數量

c1 == c2

判斷c1是否等於c2

c1 != c2

判斷c1是否不等於c2(等同於!(c1==c2))

c1 < c2

判斷c1是否小於c2

c1 > c2

判斷c1是否大於c2

c1 <= c2

判斷c1是否小於等於c2(等同於!(c2<c1))

c1 >= c2

判斷c1是否大於等於c2 (等同於!(c1<c2))

3.3 特殊的搜尋函式

  sets和multisets在元素快速搜尋方面做了優化設計,提供了特殊的搜尋函式,所以應優先使用這些搜尋函式,可獲得對數複雜度,而非STL的線性複雜度。比如在1000個元素搜尋,對數複雜度平均十次,而線性複雜度平均需要500次。

操作

效果

count (elem)

返回元素值為elem的個數

find(elem)

返回元素值為elem的第一個元素,如果沒有返回end()

lower _bound(elem)

返回元素值為elem的第一個可安插位置,也就是元素值 >= elem的第一個元素位置

upper _bound (elem)

返回元素值為elem的最後一個可安插位置,也就是元素值 > elem 的第一個元素位置

equal_range (elem)

返回elem可安插的第一個位置和最後一個位置,也就是元素值==elem的區間

3.4 賦值

操作

效果

c1 = c2

將c2的元素全部給c1

c1.swap(c2)

將c1和c2 的元素互換

swap(c1,c2)

同上,全域性函式

3.5 迭代器相關函式

  sets和multisets的迭代器是雙向迭代器,對迭代器操作而言,所有的元素都被視為常數,可以確保你不會人為改變元素值,從而打亂既定順序,所以無法呼叫變動性演算法,如remove()。

操作

效果

c.begin()

返回一個隨機存取迭代器,指向第一個元素

c.end()

返回一個隨機存取迭代器,指向最後一個元素的下一個位置

c.rbegin()

返回一個逆向迭代器,指向逆向迭代的第一個元素

c.rend()

返回一個逆向迭代器,指向逆向迭代的最後一個元素的下一個位置

3.6 安插和刪除元素

  必須保證引數有效,迭代器必須指向有效位置,序列起點不能位於終點之後,不能從空容器刪除元素。

操作

效果

c.insert(elem)

插入一個elem副本,返回新元素位置,無論插入成功與否。

c.insert(pos, elem)

安插一個elem元素副本,返回新元素位置,pos為收索起點,提升插入速度。

c.insert(beg,end)

將區間[beg,end)所有的元素安插到c,無返回值。

c.erase(elem)

刪除與elem相等的所有元素,返回被移除的元素個數。

c.erase(pos)

移除迭代器pos所指位置元素,無返回值。

c.erase(beg,end)

移除區間[beg,end)所有元素,無返回值。

c.clear()

移除所有元素,將容器清空

 Map和Multimap

1、結構

  Map和multimap將key/value pair(鍵值/實值 隊組)當作元素,進行管理。他們根據key的排序準則將元素排序。multimap允許重複元素,map不允許。

元素要求:

  • key/value必須具有assigned(可賦值)和copyable(可複製的)性質。
  • 對於排序而言,key必須具是comparable(可比較的)。

2、能力

  典型情況下,set,multisets,map,multimap使用相同的內部結構,因此可以將set和multiset當成特殊的map和multimap,只不過set的value和key指向的是同一元素。

  map和multimap會根據key對元素進行自動排序,所以根據key值搜尋某個元素具有良好的效能,但是如果根據value來搜尋效率就很低了。

  同樣,自動排序使得你不能直接改變元素的key,因為這樣會破壞正確次序,要修改元素的key,必須先移除擁有key的元素,然後插入擁有新的key/value的元素,從迭代器的觀點來看,元素的key是常數,元素的value是可以直接修改的。

3、操作函式

3.1 構造、析構、拷貝

操作

效果

map c

產生一個空的map/multimap不包含任何元素

map c(op)

以op為排序準則,產生一個空的map/multimap

map c1(c2)

產生某個map/multimap的副本,所有元素都被拷貝

map c(beg,end)

以區間[beg,end)內的元素產生一個map/multimap

map c(beg,end,op)

以op為排序準則,區間[beg,end)內的所有元素生成一個map/multimap

c.~map()

銷燬所有元素,釋放記憶體

map<Key,Elem>

一個map/multimap,以less<> (operator <)為排序準則

map<Key,Elem,Op>

一個map,以op為排序準則

3.2 非變動性操作

操作

效果

c.size()

返回當前的元素數量

c.empty()

判斷大小是否為零,等同於0 == size(),效率更高

c.max_size()

返回能容納的元素最大數量

c1 == c2

判斷c1是否等於c2

c1 != c2

判斷c1是否不等於c2(等同於!(c1==c2))

c1 < c2

判斷c1是否小於c2

c1 > c2

判斷c1是否大於c2

c1 <= c2

判斷c1是否小於等於c2(等同於!(c2<c1))

c1 >= c2

判斷c1是否大於等於c2 (等同於!(c1<c2))

3.3 特殊搜尋函式

操作

效果

count(key)

返回鍵值等於key的元素個數

find(key)

返回鍵值等於key的第一個元素,沒找到返回end()

lower_bound(key)

返回鍵值為key之元素的第一個可安插位置,也就是鍵值>=key的第一個元素位置

upper_bound(key)

返回鍵值為key之元素的最後一個可安插位置,也就是鍵值>key的第一個元素位置

equal_range(key)

返回鍵值為key之元素的第一個可安插位置和最後一個可安插位置,也就是鍵值==key的元素區間

3.4 賦值

操作

效果

c1 = c2

將c2的元素全部給c1

c1.swap(c2)

將c1和c2 的元素互換

swap(c1,c2)

同上,全域性函式

3.5 迭代器函式

  map和multimap不支援元素直接存取,因此元素的存取通常是經過迭代器進行。不過例外的是,map提供下標操作,可直接存取元素。同樣,他們的迭代器是雙向迭代器,所有的元素的key都被視為常數,不能呼叫任何變動性操作,如remove(),要移除元素,只能用塔門提供的函式。

操作

效果

c.begin()

返回一個隨機存取迭代器,指向第一個元素

c.end()

返回一個隨機存取迭代器,指向最後一個元素的下一個位置

c.rbegin()

返回一個逆向迭代器,指向逆向迭代的第一個元素

c.rend()

返回一個逆向迭代器,指向逆向迭代的最後一個元素的下一個位置

3.6 元素的安插和移除

操作

效果

c.insert(elem)

插入一個elem副本,返回新元素位置,無論插入成功與否。

c.insert(pos, elem)

安插一個elem元素副本,返回新元素位置,pos為收索起點,提升插入速度。

c.insert(beg,end)

將區間[beg,end)所有的元素安插到c,無返回值。

c.erase(elem)

刪除與elem相等的所有元素,返回被移除的元素個數。

c.erase(pos)

移除迭代器pos所指位置元素,無返回值。

c.erase(beg,end)

移除區間[beg,end)所有元素,無返回值。

c.clear()

移除所有元素,將容器清空

  有三個不同的方法將value插入map:

  • 運用value_type,為了避免隱式轉換,可以使用value_type明白傳遞正確型別。value_type是容器本身提供的型別定義
std::map<std::string,float> coll;
 ...
coll.insert(std::map<std::string,float>::value_type("otto",22.3));
  • 運用pair,另一個作法是直接運用pair<>。

複製程式碼

std::map<std::string,float> coll;
...
//use implicit conversion:
coll.insert(std::pair<std::string,float>("otto",22.3));
//use no implicit conversion:
coll.insert(std::pair<const std::string,float>("otto",22.3));

複製程式碼

  上述第一個insert()語句內的型別並不正確,所以會被轉換成真正的型別。
  • 運用make_pair()
  最方便的方法是直接運用make_pair()函式,這個函式根據傳入的兩個引數構造一個pair物件。

複製程式碼

std::map<std::string,float> coll;
    ...
coll.insert(std::make_pair("otto",22.3));
下面是個簡單例子,檢查安插元素是否成功:
std::map<std::string,float> coll;
   ...
   if (coll.insert(std::make_pair("otto",22.3)).second) {
       std::cout << "OK, could insert otto/22.3" << std::endl;
   }
   else {
       std::cout << "Oops, could not insert otto/22.3 "
                 << "(key otto already exists)" << std::endl;
   }

複製程式碼

  如果要移除某個值為value的元素,使用erase()即可。

   std::map<std::string,float> coll;
   ...
   //remove all elements with the passed key
   coll.erase(key);

  如果multimap內喊重複元素,不能使用erase()來刪除這些元素的第一個,但是可以這麼做:

複製程式碼

typedef multimap<string.float> StringFloatMMap;
   StringFloatMMap coll;
   ...
   //remove first element with passed key
   StringFloatMMap::iterator pos;
   pos = coll.find(key);
   if (pos != coll.end()) {
       coll.erase(pos);
   }

複製程式碼

  這裡使用成員函式的find()而非STL裡面的find(),因為成員函式更快,然而不能使用成員函式find()來移除擁有某個value(而非某個key)的元素。

  移除元素時,要當心心意外發生,當移除迭代器所指物件時,可能使迭代器失效。

複製程式碼

typedef std::map<std::string,float> StringFloatMap;
   StringFloatMap coll;
   StringFloatMap::iterator pos;
   ...
   for (pos = coll.begin(); pos != coll.end(); ++pos) {
        if (pos->second == value) {
            coll. erase (pos);                   // RUNTIME ERROR !!!
        }
   }

複製程式碼

  對pos所指元素實施erase(),會使pos不再成為一個有效的迭代器,如果此後未對pos重新設值就使用pos,會出現異常。++pos就能導致一個未定義行為。下面是正確的刪除方法。

複製程式碼

 typedef std::map<std::string,float> StringFloatMap;
   StringFloatMap coll;
   StringFloatMap::iterator pos;
   ...
   //remove all elements having a certain value
   for (pos = c.begin(); pos != c.end(); ) {
       if (pos->second == value) {
           c.erase(pos++);
       }
       else {
           ++pos;
       }
   }

複製程式碼

  注意,pos++會指向下一個元素,但返回其原始值(指向原位置)的一個副本,因此,當erase()被呼叫,pos已經不指向那個即將被刪除的元素了。

4、map視為關聯陣列

  通常,關聯陣列不提供直接存取,必須依靠迭代器,不過map是個例外,map提供下標操作符,可以直接存取元素。不過下標操作符的索引不是元素整數位置,而是元素的key。也就是說,索引可以是任何型別,而非侷限的整數型別。

操作

效果

m[key]

返回一個reference,指向鍵值為key的元素,如果該元素尚未存在,插入該元素。

  和一般陣列的區別不僅僅是索引型別,你不能使用一個錯誤的索引,如果你是用某個key為索引,容器尚未存在該元素,會自動安插該元素,新元素由default構造,所有基本型別都提供default建構函式,以零為初始值。

關聯陣列的行為方式有優點,也有缺點:

  優點是可以透過方便的介面向map安插新元素。

複製程式碼

   std::map<std::string,float> coll;     // empty collection
   /*insert "otto"/7.7 as key/value pair
    *-first it inserts "otto"/float()
    *-then it assigns 7.7
    */
   coll["otto"] = 7.7;

複製程式碼

  其中的語句:coll["otto"] = 7.7;處理如下:

  1.處理coll["otto"]:

  --如果存在鍵值為“otto”的元素,以上式子返回該元素的reference。

  --如果沒有任何元素的鍵值為“otto”,以上式子便為map自動安插一個新元素,鍵值key為“otto”,value通過default建構函式完成,並返回一個reference指向新元素。

  2.將7.7賦值給value:

  --緊接著,將7.7賦值給剛才返回的元素。

  這樣,map之內就包含了一個鍵值(key)為“otto”的元素,其值(value)為7.7。

      缺點就是你可能不小心誤置新元素。例如你想列印key為“otto”的元素值:

  std::cout << coll[“ottto”] << endl;

      它會安插一個鍵值為“ottto”的元素,然後列印其值,預設情況下是0。它並不會告訴你拼寫錯誤,並且插入一個你可能不需要的元素。

      這種插入方式比一般的map安插方式來得慢,因為在生成新元素的時候,需要使用default建構函式將新元素初始化,而這個值馬上又會被真正的value覆蓋。

String

1:string物件的定義和初始化以及讀寫

string s1;      預設建構函式,s1為空串

string s2(s1);   將s2初始化為s1的一個副本

string s3("valuee");   將s3初始化一個字串面值副本

string s4(n,'c');   將s4 初始化為字元'c'的n個副本

cin>>s5;  讀取有效字元到遇到空格

getline(cin,s6);  讀取字元到遇到換行,空格可讀入,知道‘\n’結束(練習在下一個程式碼中),

getline(cin,s7,'a'); 一個直到‘a’結束,其中任何字元包括'\n'都能夠讀入,可以試試題:UVa10361

2:string物件操作

s.empty()  判斷是否為空,bool型

s.size() 或 s.length() 返回字元的個數

s[n]  返回位置為n的字元,從0開始計數

s1+s2 連線,看下面例子:

    可用此方法給字串後面新增字元如:s=s+'a'; 

    a:  string s2=s1+", ";  //對,把一個string物件和一個字元面值連線起來是允許的

    b:  string s4="hello "+", ";   //錯,不能將兩個字串面值相加

    c:  string s5=s1+", "+"world";   //對,前面兩個相加相當於一個string物件;

    d:  string s6="hello" + ", " +  s2;  //錯

(注:字串尾部追加還可用s.append("abc")函式新增)

s1=s2  替換

s1==s2  相等,返回true或false

!=,<,<=,>,>=  字串比較,兩個字串短的與長的前面匹配,短的小於長的

3:string物件中字元的處理(標頭檔案cctype)

    isalnum(c)  如果c是字母或數字,返回 true

    isalpha(c)  如果c是字母,返回true

    iscntrl(c)  c是控制符,返回true

    isdigit(c)  如果c是數字,返回true

    isgraph(c)  如果c不是空格,則可列印,,則為true

    islower(c)  如果c是小寫字母,則為true

<