C++進階篇一:C++ 標準模板庫之容器和迭代 頂 原

C++容器

容器(container)是C++中能夠存儲幾乎任何數據類型的數據結構,分爲一級容器、容器適配器以及類容器。不同的容器有一些共同的成員函數,通過迭代(在性質上與指針相似)可以實現對容器元素的操作。不同容器支持的迭代(具體來說是迭代權限)是不同的,這也決定了它們所能用於的算法是不同的(因爲每種算法都有其特定支持的迭代類型)。內置數組也可以作爲標準庫算法的操作對象,此時它的指針就作爲迭代。

以下爲C++容器共有的成員函數:

  • 默認構造函數:初始化一個空容器
  • 複製構造函數:複製一個現存同類型容器
  • 移動構造函數:(C++11)將一個容器中的內容移到另一個同類型容器中
  • 析構函數:詳見https://my.oschina.net/SamYjy/blog/828146
  • empty方法:判斷容器是否爲空
  • size方法:返回容器中現有元素個數,forward_list不能用
  • max_size方法:返回一個容器中所能融入的最大元素個數
  • operator=:用於複製容器內容。特別地,在C++11中用於移動容器內容。
  • operator<, operator<=, operator>, operator>=, operator==, operator!=:比較不同容器之間的屬性
  • insert方法:向容器中插入元素
  • swap方法:交換兩個容器的元素,C++11中作爲一個使用移動構造函數的全局函數,用於交換同類型容器的地址。
  • begin方法:可返回iterator或const_iterator,用於指向容器的第一個元素
  • end方法:可返回iterator或const_iterator,用於指向容器最後一個元素的後一個位置
  • rbegin方法:可返回iterator或const_iterator,用於指向容器的最後一個元素
  • rend方法:可返回iterator或const_iterator,用於指向容器的第一個元素的前一個位置
  • cbegin:(C++11)返回const_iterator,用於指向容器的第一個元素
  • cend, crbegin和crend則可以以此類推
  • erase:從容器中刪除一個或多個元素
  • clear:刪除容器中所有元素(對array不適用)

C++容器共有函數使用注意點:

  1. <, <=, >, >=, ==和!=不能用於優先隊列
  2. <, <=, >和 >=不能用於非順序關聯型容器(後面會詳細解釋)
  3. rbegin, rend, crbegin和crend不能用於forward_list

各類型容器簡介如下:

一級容器:

一級容器分爲序列型容器、順序關聯型容器和非順序關聯型容器。

  • 序列型容器:vector,deque, list, forward_list(爲單鏈表,C++11新特性), array
  • 順序關聯型容器(容器中的key是排序好的):set和map(不允許重複key,此外在C++11中key是不可修改的), multiset和multimap(允許重複的key,此外在C++11中key是不可修改的)。這些頭文件分別是<set>和<map>
  • 非順序關聯型容器(因爲容器中的key未排序,所以性能方面可能更出色):unsorted_set, unsorted_map, unsorted_multiset和unsorted_multimap,用法與對應的順序關聯型容器類似。

在具體的算法實現方面,如果需要在容器最後進行頻繁插入刪除操作的話,則vector是一個理想的選擇(因爲vector爲連續存儲結構);如果需要頻繁在兩頭進行插入刪除操作,則deque是一個理想選擇;如果需要在任意位置進行插入或刪除操作,則list是一個理想選擇。 **容器適配器:**棧、隊列和優先隊列 **類容器:**內置數組、比特集合(bitsets,用於對於標誌集合(即flag values)和數值數組進行快速數學向量運算時使用)

C++各容器特有常用函數歸納:

序列型容器:

  • assign(n, val):將容器中的元素改爲出現n次的val值。
  • assign(iters_begin, iters_end):將元素中的元素改爲從begin到end的一個序列。

vector 容器(使用見例2和例3)

  • push_back(val):在vector末尾添加一個val元素
  • size:返回vector中元素的個數
  • capacity: 返回vector中能夠存儲的最多元素的個數
  • shift_to_fit:使得capacity與size相同,但是視編譯環境不同,此指令可能被忽略。
  • at(index): 讀寫相應index的元素,對index範圍作出檢查。
  • insert(iter_index, ele):在用迭代(以begin()或cbegin()作爲0加index)計算出來的index處插入ele。
  • insert(iter_insert_index, iter_start_range, iter_end_range):在被插入元素的(用迭代表示的)insert_index處插入(用迭代表示的)從start_range到end_range的一個系列。
  • erase(iter_index):刪除迭代表示的index處相應元素。
  • erase(iter_begin, iter_end):刪除用迭代表示的從begin到end的元素。
  • front:返回指向第一個元素的地址。
  • back:返回最後一個元素的地址。

list 容器(使用見例4)

  • push_front(ele):在list前端增加元素ele,此方法僅適用於forward_list, list和queue。
  • push_back(ele):類似vector的同名函數
  • sort:注意此處的sort與STL的sort是不同的,list特有的sort無傳入參數並且默認對list中的元素按非降序排序。
  • reverse():將列表中的元素倒置。
  • splice(iter_insert_index, list& b):將list b插入本list由iterator指定的下標處並將其中所有元素刪除。
  • splice(iter_insert_index, list& b, iter_delete_index):從list b中刪除由迭代delete_index確定的那一個元素,並將list b中所有元素插入insert_index後刪除list b中的所有元素。
  • splice(iter_insert_index, list& b, iter_start_delete_index, iter_end_delete_index):從list b中刪除由迭代start_delete到end_delete中的一個範圍內的元素,並將list b中所有元素插入insert_index後刪除list b中的所有元素。
  • merge(list &b):(前提是本列表和列表b都已經排好序)將list b元素merge到本列表中,默認爲升序排列。
  • unique():刪除列表中重複的元素,每個元素僅出現一次。
  • swap(list &b):將本列表與b列表的所有元素對換。
  • remove(ele):從list中刪去ele元素。
  • remove_if(未完待續)

deque 容器

與所有的vector操作基本類似,又增加了push_front和pop_front方法。

關聯型容器:

  • find(x):在容器中尋找x元素並返回x元素位置的迭代。若未找到x,則返回end()位置的迭代。

multiset< T, compareObj >: (使用見例5),T爲元素類型,compareObj爲比較方式,一般情況下爲less<T>

  • count(val):統計元素val在multiset中出現的次數
  • insert(val):將元素val插入multiset
  • insert(iter_index, val):將元素val插入iter_index
  • insert(a.iter_start(), a.iter_end()):將a容器一定範圍內的值插入multiset,注意iter_start和iter_end表示反應容器元素下標的迭代
  • lower_bound(x):返回該元素最早出現的位置下標的迭代。若不存在該元素返回end位置的迭代。
  • upper_bound(x):返回該元素最晚出現的位置下標的迭代。若不存在該元素返回end位置的迭代。
  • equal_range(x):返回包含lower_bound和upper_bound兩個迭代的一對元素對象(pair object),一般被賦值給自動類型的變量(如auto p)。分別用p.first和p.second兩個常量獲得。在去指針化時要注意這兩個指針沒有指向end()或rbegin()以及類似實際不存在元素的位置。

set: 與multiset一樣,除了插入重複key時操作會被忽略。

multimap<T1, T2, compareObj>:(使用見例6)此處compareObj針對的是key。multimap建立了從鍵到值的多對一關係。

特別地,在C++11中,一個多重映射的初始化可以寫成例如如下的形式:

multimap<int, double, less<int> > mMaps = 
 { {10, 22.2}, {20, 9.345}, {5, 77.4} };
  • make_pairs:一般使用方式爲mMap.insert(make_pair(key, val)); 用於向multimap中插入鍵值對。
  • insert(pairObj):像multimap中插入一個組對象。
  • insert({key, val}):以列表初始化的方式插入鍵值對。
  • pair.first:取得某個鍵值對的鍵。
  • pair.second:取得某個鍵值對的值。
  • count(key):統計key這個鍵在multimap中出現的次數。

map:在C++中用來表示嚴格的一對一映射。

在multimap的基礎上多了用下標讀取的功能。如pairs[25]表示讀取map pairs中鍵爲25的值。

容器適配器:

棧(頭文件<stack>):C++中,棧可用vector, list或者deque實現(默認爲deque實現)。舉例如下:

stack<int> intDequeStack; //Stack with underlying deque.
stack<int, vector<int> > intVStack; //Stack with underlying vector
stack<int, list<int> > intListStack; //Stack with underlying list
  • push(x):將x元素入棧
  • pop():將棧頂元素出棧
  • top():返回棧最頂端元素,不推出

隊列(頭文件<queue>):同樣,隊列也可以由vector, list或者deque實現(默認爲deque實現)。常用方法如下:

  • push(x):將元素x插入隊尾。
  • front():獲取隊列頭元素的地址(不推出)
  • back():獲取隊列尾元素的地址(不推出)
  • pop():將隊列頭元素出隊

優先隊列:包含功能與隊列完全一致,只是自動將最大的元素通過調堆放在隊頭。算法上的實現方式爲堆(heap)。可以通過聲明comparator改變推出順序。

類容器:

bitset:編譯時尺寸固定的一種用來操作比特集合的容器。定義容器示例:

//Size is an unsigned integer:
bitset<size> b;
  • set(index):將index處的比特值設爲on
  • reset(index):將index處的比特值設爲off
  • flip:將所有位倒置
  • index:獲得所在爲的地址,不作下標檢查
  • at(index):獲得所在爲的地址,作下標檢查
  • test(index):作下標檢查,返回所在位的下標的布爾值。on爲true,off爲false
  • count:返回比特集合中下標on的位數
  • any:若比特集合中有位是on,則返回true
  • all:若比特集合中所有位都是on,則返回true
  • none:若比特集合中所有位都是off,則返回true == / !=:比較兩個比特集合是否相等 &= / != / ^=/ |= / >>= (右移)/ <<=(左移):進行比特集合運算 to_string / to_ulong():分別返回比特集合的string和無符號長整數

C++迭代器

C++的迭代用於指向一級容器、序列或範圍(sequences or ranges,比如輸入流和輸出流),適用前面提到的begin和end方法。其中,迭代器的權限從高到低分爲任意存取(random access)、雙向迭代(bidiretional)、單向迭代(forward)以及輸入輸出流(input和output,屬於同級別)。其中,高級權限的迭代器擁有本級別以及所有低於其級別的迭代權限。

各個迭代權限所對應的操作如下(從高級別權限到低級別權限):

  1. 隨機存取級別:p += i, p -= i, p + i, i + p, p - i, p[i](從p所指位置開始存取對應第加i個位置操作), p - p1(p和p1的距離之差), p < p1(p的位置是否在p1之前), p <= p1, p > p1以及p >= p1
  2. 雙向迭代:--p, p--
  3. 向前迭代:提供所有輸入和輸出級別的操作
  4. 輸出迭代:*p, p1 = p2
  5. 輸入迭代:*p, p->m(通過迭代讀取元素m), p1 == p2, p1 != p2
  6. 所有級別:++p, p++, p1 = p2 (將迭代p2賦給迭代p1)

注意:++操作對於反向迭代對象(reverse_iterator和const_reverse_iterator)來說是指向當前元素的前一個元素。

前文提到,不同的一級容器所對應的迭代權限是不同的,各一級容器的迭代權限如下:

  1. 隨機存取級別:vector, array, deque
  2. 雙向迭代級別:list, 順序關聯型容器、非順序關聯型容器
  3. 向前迭代級別:forward_list

C++標準模版容器常用異常

  • out_of_range:提示下標越界,例如常與at方法結合使用。
  • invalid_argument:提示函數被傳入無效參量。
  • length_error:提示被創建容器中元素過多。
  • bad_alloc:提示內存不足,使用new函數創建內存時失敗。

以下爲若干C++ 標準模版庫使用的例子:

例1:使用輸入流讀取兩個整數進行相加:

// Fig. 15.4: fig15_04.cpp
// Demonstrating input and output with iterators.
#include <iostream>
#include <iterator> // ostream_iterator and istream_iterator
using namespace std;

int main()
{
   cout << "Enter two integers: ";

   // create istream_iterator for reading int values from cin
   istream_iterator< int > inputInt( cin );

   int number1 = *inputInt; // read int from standard input
   ++inputInt; // move iterator to next input value
   int number2 = *inputInt; // read int from standard input

   // create ostream_iterator for writing int values to cout
   ostream_iterator< int > outputInt( cout );

   cout << "The sum is: ";
   *outputInt = number1 + number2; // output result to cout
   cout << endl;
} // end main

輸入圖片說明

本例中,ostream_iterator<int>爲只輸出int類型(或其兼容類型)的輸出流,它的頭文件是<iterator>

例2: vector擴展、獲取容量以及元素數量、迭代器使用若干操作

// Fig. 15.10: Fig15_10.cpp
// Demonstrating Standard Library vector class template.
#include <iostream>
#include <vector> // vector class-template definition
using namespace std;

// prototype for function template printVector
template < typename T > void printVector( const vector< T > &integers2 );

int main()
{
   const size_t SIZE = 6; // define array size
   int values[ SIZE ] = { 1, 2, 3, 4, 5, 6 }; // initialize values
   //vector< int > integers(4); // create vector of ints
   vector<int> integers;
   
   cout << "The initial size of integers is: " << integers.size()
      << "\nThe initial capacity of integers is: " << integers.capacity();

   // function push_back is in vector, deque and list
   for(int i = 0; i < (sizeof(values) / sizeof(int)) ; i++)
       integers.push_back(values[i]);
   
   //Size is 7 and capacity becomes 8 in this case.
   cout << "\nThe size of integers is: " << integers.size()
      << "\nThe capacity of integers is: " << integers.capacity();
   
      //Cause the vector to be cleaned up: integers.resize(4);
   integers.shrink_to_fit();
   cout << "\nThe size of integers is: " << integers.size()
      << "\nThe capacity of integers is: " << integers.capacity();
   
   cout << "\n\nOutput built-in array using pointer notation: ";
   // display values using pointer notation
   for ( const int *ptr = begin( values ); ptr != end( values ); ++ptr )
      cout << *ptr << ' ';
   
   cout << endl;
   cout << "Output vector using ptr notation: ";
   
   for(auto ptr = begin(integers); ptr != integers.end(); ptr++)
       cout << *ptr << ' ';

   cout << "\nOutput vector using iterator notation: ";
   printVector( integers );
   cout << "\nReversed contents of vector integers: ";

   // display vector in reverse order using const_reverse_iterator
   for ( auto reverseIterator = integers.crbegin();               
      reverseIterator!= integers.crend(); ++reverseIterator )
      cout << *reverseIterator << ' ';       

   cout << endl;
} // end main

// function template for outputting vector elements
template < typename T > void printVector( const vector< T > &integers2 )
{
   // display vector elements using const_iterator
   for ( auto constIterator = integers2.cbegin(); 
      constIterator != integers2.cend(); ++constIterator )
      cout << *constIterator << ' ';
   
   cout << endl;
   
//   //Can also be following way:
//   for(auto const item : integers2)
//       cout << item << ' ';
} // end function printVector

輸入圖片說明

注意:capacity方法視編譯器不同,效果可能不同。調用shrink_to_fit()方法(C++11中)能夠使得容器的capacity和元素個數相等。

例3:Vector insert, copy, erase, clean以及異常處理

// Fig. 15.11: fig15_11.cpp
// Testing Standard Library vector class template 
// element-manipulation functions.
#include <iostream>
#include <array> // array class-template definition
#include <vector> // vector class-template definition
#include <algorithm> // copy algorithm                  
#include <iterator> // ostream_iterator iterator
#include <stdexcept> // out_of_range exception
using namespace std;

int main()
{
//   const size_t SIZE = 6;   
//   array< int, SIZE > values = { 1, 2, 3, 4, 5, 6 };
//   vector< int > integers(values.cbegin(), values.cend());
   
    int values[] = {1, 2, 3, 4, 5, 6};
    vector<int> integers;
    integers.insert(integers.begin(), begin(values), end(values));
//    for(int i : values)
//        integers.push_back(i);
   
   ostream_iterator< int > output( cout, " " );

   cout << "Vector integers contains: ";
   copy( integers.cbegin(), integers.cend(), output );

   cout << "\nFirst element of integers: " << integers.front()
      << "\nLast element of integers: " << integers.back();

   integers[ 0 ] = 7; // set first element to 7
   integers.at( 2 ) = 10; // set element at position 2 to 10

   // insert 22 as 2nd element
   integers.insert( integers.cbegin() + 1, 22 );  

   cout << "\n\nContents of vector integers after changes: ";
   copy( integers.cbegin(), integers.cend(), output );

   // access out-of-range element
   try 
   {
      integers.at( 100 ) = 777;   
   } // end try
   catch ( out_of_range &outOfRange ) // out_of_range exception 
   {
      cout << "\n\nException: " << outOfRange.what();
   } // end catch

   // erase first element
   integers.erase( integers.cbegin() );
   cout << "\n\nVector integers after erasing first element: ";
   copy( integers.cbegin(), integers.cend(), output );

   // erase remaining elements
   integers.erase( integers.cbegin(), integers.cend() );
   cout << "\nAfter erasing all elements, vector integers " 
      << ( integers.empty() ? "is" : "is not" ) << " empty";

   //insert elements from the array values
   //integers.insert( integers.cbegin(), values.cbegin(), values.cend() );
   
   //If values is a built in type array, this sentence is:
   integers.insert(integers.cbegin(), begin(values), end(values));
   
   cout << "\n\nContents of vector integers before clear: ";
   copy( integers.cbegin(), integers.cend(), output );

   // empty integers; clear calls erase to empty a collection
   integers.clear();  
   cout << "\nAfter clear, vector integers " 
      << ( integers.empty() ? "is" : "is not" ) << " empty" << endl;
} // end main

輸入圖片說明

  • 此例中,copy方法(頭文件<algorithm>)的三個參數分別爲輸入容器的起始位置、輸入容器的結束位置(不包括)以及輸出容器。
  • 此外,front方法和back方法分別返回第一個元素的地址以及最後一個元素的地址。注意begin方法是返回指向第一個元素的隨即存儲迭代,而end方法返回指向最後一個元素後一個位置的隨機存儲迭代。此外,調用front和end方法時必須確保容器非空,否則將會取得未定義參數。
  • 另:at方法跟用下標的區別在於at方法對於迭代越界進行檢查,越界時拋出out_of_range異常。
  • insert方法:可被使用在任意類型的順序序列(除了array和forward_list,原因是array尺寸固定,forward_list只有insert_after方法),將元素插入到特定位置(從begin到end,但不包括end)。其他版本的insert能將同一個元素插入多次或者插入一列元素。如如下代碼在第二個元素的位置插入22這個值4遍:
// insert 22 at 2nd element 4 times
integers.insert(integers.begin() + 1, 4, 22);
  • erase方法可以刪除某一個或某一範圍內的特定元素(除了array不能刪除以及forward_list用的是erase_after之外)。注意erase方法通常刪除容器相應位置的對象,但是對於動態分配的內存並沒有delete內存,從而可能導致內存泄漏。對於unique_ptr來說,erase可以刪除分配的內存以及銷燬指針;對於shared_ptr來說,地址計數會被降低,並且在在地址計數變爲0的情況下,內存也會被刪除。

例4:list容器使用示例:

// Fig. 15.13: Fig15_13.cpp
// Standard library list class template.
#include <iostream>
#include <array>
#include <list> // list class-template definition
#include <algorithm> // copy algorithm
#include <iterator> // ostream_iterator
using namespace std;

// prototype for function template printList
template < typename T > void printList( const list< T > &listRef );

int main()
{ 
   const size_t SIZE = 4;
   array< int, SIZE > ints = { 2, 6, 4, 8 };
   list< int > values; // create list of ints
   list< int > otherValues; // create list of ints

   // insert items in values
   values.push_front( 1 );
   values.push_front( 2 );
   values.push_back( 4 );
   values.push_back( 3 );
   
   cout << "values contains: ";
   printList( values );

   values.sort(); // sort values
   cout << "\nvalues after sorting contains: ";
   printList( values );
  
   // insert elements of ints into otherValues                   
   otherValues.insert( otherValues.cbegin(), ints.cbegin(), ints.cend() );
   cout << "\nAfter insert, otherValues contains: ";
   printList( otherValues );

   // remove otherValues elements and insert at end of values
   values.splice( values.cend(), otherValues );
   cout << "\nAfter splice, values contains: ";
   printList( values );

   values.sort(); // sort values
   cout << "\nAfter sort, values contains: ";
   printList( values );

   // insert elements of ints into otherValues
   otherValues.insert( otherValues.cbegin(), ints.cbegin(), ints.cend() );
   otherValues.sort(); // sort the list
   cout << "\nAfter insert and sort, otherValues contains: ";
   printList( otherValues );
   
   // remove otherValues elements and insert into values in sorted order
   values.merge( otherValues );                         
   cout << "\nAfter merge:\n   values contains: ";
   printList( values );
   cout << "\n   otherValues contains: ";
   printList( otherValues );

   values.pop_front(); // remove element from front
   values.pop_back(); // remove element from back
   cout << "\nAfter pop_front and pop_back:\n   values contains: ";
   printList( values );

   values.unique(); // remove duplicate elements
   cout << "\nAfter unique, values contains: ";
   printList( values );

   // swap elements of values and otherValues
   values.swap( otherValues );
   cout << "\nAfter swap:\n   values contains: ";
   printList( values );
   cout << "\n   otherValues contains: ";
   printList( otherValues );

   // replace contents of values with elements of otherValues
   values.assign( otherValues.cbegin(), otherValues.cend() );
   cout << "\nAfter assign, values contains: ";
   printList( values );

   // remove otherValues elements and insert into values in sorted order
   values.merge( otherValues ); 
   cout << "\nAfter merge, values contains: ";
   printList( values ); 
   
   values.remove( 4 ); // remove all 4s
   cout << "\nAfter remove( 4 ), values contains: ";
   values.reverse();
   printList( values );
   cout << endl;
} // end main

// printList function template definition; uses 
// ostream_iterator and copy algorithm to output list elements
template < typename T > void printList( const list< T > &listRef )
{
   if ( listRef.empty() ) // list is empty
      cout << "List is empty";
   else 
   {
      ostream_iterator< T > output( cout, " " );
      copy( listRef.begin(), listRef.end(), output );
   } // end else
} // end function printList

輸入圖片說明

例 5:multiset以及unordered_multiset使用示例:

// Fig. 15.15: Fig15_15.cpp
// Standard Library multiset class template
#include <iostream>
#include <array> 
#include <set> // multiset class-template definition
#include <algorithm> // copy algorithm
#include <iterator> // ostream_iterator
using namespace std;

int main()
{
   const size_t SIZE = 10;
   array< int, SIZE > a = { 7, 22, 9, 1, 18, 30, 100, 22, 85, 13 };
   //There should be a space between the right > of int and the right > of multiset
   //Otherwise compiling error may occur.
   multiset< int, less< int > > intMultiset; // multiset of ints
   ostream_iterator< int > output( cout, " " );

   cout << "There are currently " << intMultiset.count( 15 )
      << " values of 15 in the multiset\n";
   
   intMultiset.insert( 15 ); // insert 15 in intMultiset
   intMultiset.insert( 15 ); // insert 15 in intMultiset
   cout << "After inserts, there are " << intMultiset.count( 15 )
      << " values of 15 in the multiset\n\n";

   // find 15 in intMultiset; find returns iterator
   auto result = intMultiset.find( 15 );  

   if ( result != intMultiset.end() ) // if iterator not at end
      cout << "Found value 15\n"; // found search value 15
   
   // find 20 in intMultiset; find returns iterator
   result = intMultiset.find( 20 );

   if ( result == intMultiset.end() ) // will be true hence
      cout << "Did not find value 20\n"; // did not find 20

   // insert elements of array a into intMultiset
   intMultiset.insert( a.cbegin(), a.cend() ); 
   cout << "\nAfter insert, intMultiset contains:\n";
   copy( intMultiset.cbegin(), intMultiset.cend(), output );

   // determine lower and upper bound of 22 in intMultiset
   cout << "\n\nLower bound of 22: " 
      << *( intMultiset.lower_bound( 22 ) );
   cout << "\nUpper bound of 22: " << *( intMultiset.upper_bound( 22 ) );

   // use equal_range to determine lower and upper bound 
   // of 22 in intMultiset
   auto p = intMultiset.equal_range( 22 );

   cout << "\n\nequal_range of 22:" << "\n   Lower bound: " 
      << *( p.first ) << "\n   Upper bound: " << *( p.second );
   cout << endl;

   int count = 0;
   while(p.first != intMultiset.begin()){
        p.first--;
        count ++;
   }      
   
   cout << "p.first is the " << count << "th index in the set. " << endl;
   cout << endl;

   unordered_set<int> intSet;
   intSet.insert(a.begin(), a.end());
   copy( intMultiset.cbegin(), intMultiset.cend(), output );
} // end main

輸入圖片說明

備註:所有順序關聯型容器中的key(在set中key即元素)必須支持比較型功能函數。在比較類型的聲明中(此處爲less<int>),被比較的類型必須要與比較功能函數相對應(此處爲operator<)。

例6 multimap使用示例

// Fig. 15.17: Fig15_17.cpp
// Standard Library multimap class template.
#include <iostream>
#include <map> // multimap class-template definition
using namespace std;

int main()
{
   multimap< int, double, less< int > > pairs; // create multimap

   cout << "There are currently " << pairs.count( 15 )
      << " pairs with key 15 in the multimap\n";

   // insert two value_type objects in pairs
   pairs.insert( make_pair( 15, 2.7 ) );
   pairs.insert( make_pair( 15, 99.3 ) );
   
   cout << "After inserts, there are " << pairs.count( 15 )
      << " pairs with key 15\n\n";
   
   auto val1 = make_pair( 30, 111.11 );
   // insert five value_type objects in pairs
   pairs.insert( val1 );
   pairs.insert({10, 22.2} );
   pairs.insert( make_pair( 25, 33.333 ) );
   pairs.insert( make_pair( 20, 9.345 ) );
   pairs.insert( make_pair( 5, 77.54 ) );
   
   cout << "Multimap pairs contains:\nKey\tValue\n";
   
   // walk through elements of pairs
   for ( auto mapItem : pairs )
      cout << mapItem.first << '\t' << mapItem.second << '\n';

   cout << endl;
} // end main

輸入圖片說明

參考資料:

Paul Deitel & Harvey Deitel, C++11程序設計(英文版)(第2版)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章