1. 程式人生 > >C++ 10.3 關聯容器map定義以及value_type、key_type、mapped_type

C++ 10.3 關聯容器map定義以及value_type、key_type、mapped_type

簡介

  • map是<鍵—值>對的集合 如:map< string ,int> word_count。map型別通常可理解為關聯陣列:可使用鍵作為下標來獲取一個值,正如內建陣列型別一樣。而關聯的本質在於元素的值與某個特定的鍵相關聯,而並非通過元素在陣列中的位置來獲取。

  • 要使用map物件,則必須包含map 標頭檔案。 #include < map >. 在定義map 物件時,必須分別指明鍵和值的型別:

  • 記住!!!在vector < string,list< int > > 這種容器裡邊的型別也是容器的時候 >之間是有空格的,不然就變成>>運算子了

  • 對於鍵型別,唯一得約束就是必須支援 < 操作符,其他不作要求。所以,不能拿(list 型別的迭代器)做鍵型別,因為(9.2節)list 的迭代器不支援算術運算,也不支援關係運算。它只支援前置和後置的自增、自減運算以及相等(不相等)運算。

  • value_type該型別比前面介紹的容器所使用的元素型別要複雜得多,value_type 是儲存元素的鍵以及值的pair型別,而且鍵為const。所以鍵初始化之後是不能再被賦值的

  • 在學習map的介面時,需要謹記value_type 是pair型別的,它的值成員可以修改,但鍵成員不能修改!!!!。

    • 使用下標訪問map與使用下標訪問陣列或vector的行為截然不同:用下標訪問不存在的元素將導致在map容器中新增一個新的元素,它的鍵即為該下標值。
  • 有別於vector或string型別,map下標操作符返回的型別與對map迭代器進行解引用獲得的型別不相同。

    • 顯然,map迭代器返回value_type型別(pair型別)的值—–包括const key_type 和mapped_type型別成員的pair物件;下標操作符返回的是儲存在map裡面的值,是一個mapped_type型別的值。
  • map類額外定義了兩種型別:key_type、mapped_type,以獲得鍵或值的類

=================================================================================================

一、map物件的定義

  • map是<鍵—值>對的集合 。map型別通常可理解為關聯陣列:可使用鍵作為下標來獲取一個值,正如內建陣列型別一樣。而關聯的本質在於元素的值與某個特定的鍵相關聯,而並非通過元素在陣列中的位置來獲取。

1、map 物件的定義———-是一個<鍵—值>對的集合

  • 要使用map物件,則必須包含map 標頭檔案。 #include . 在定義map 物件時,必須分別指明鍵和值的型別:
map<string,int> word_count;//空的map物件,由string型別的鍵索引,關聯的值則為int型別。

這裡寫圖片描述

2、鍵型別的約束————必須能夠進行 < 操作

  • 在使用關聯容器時,它的鍵不但有一個型別,而且還有一個相關的比較函式。預設情況下,標準庫使用鍵型別定義的 < 操作符類實現鍵的比較。15.8.3 會再介紹

  • 所用的比較函式必須在鍵型別上定義嚴格弱排序。所謂的嚴格弱排序可理解為鍵型別資料上的”小於“關係。

  • 實際應用中,鍵型別必須定義 < 操作符,而且該操作符應能“正確地工作”

  • 對於鍵型別,唯一得約束就是必須支援 < 操作符,其他不作要求。

//如果我們已經定義了一個ISBN的型別,這個是為書進行編號的。
 map<ISBN,Sale_item> bookstore;
 //以ISBN型別的物件為索引,所有元素都儲存了一個關聯的Sale_item類型別例項。
//習題 10.6

//解答:可以定義map物件以vector<int>::iterator 和pair <int,string>為鍵關聯int型物件。但是不能定義map物件以list<int>::iterator 為鍵關聯int型物件。因為鍵型別必須支援 < 操作,而list 容器的迭代器型別不支援<操作 (9.2節)。 

二、map定義的型別——value_type型別是pair型別的

類似於順序容器裡面定義了size_type 型別(vector< int>: : size_type),map也定義了自己的型別。

這裡寫圖片描述

上圖是順序容器裡面定義的型別,有些同樣適用於map。

這裡寫圖片描述
- map 物件的元素是鍵–值對,也即每個元素包含兩個部分:鍵以及由鍵關聯的值。map 的value_type 就反映了這個事實。

  • 該型別比前面介紹的容器所使用的元素型別要複雜得多,value_type 是儲存元素的鍵以及值的pair型別,而且鍵為const型別,所以鍵初始化之後是不能再被賦值的。如word_count陣列的value_type為pair

map<string,int> word_count;//空的map物件,由string型別的鍵索引,關聯的值則為int型別。

1、map迭代器進行解引用將產生pair型別的物件

  • 對迭代器進行解引用時,將獲得一個引用,指向容器中一個value_type型別的值。對於map容器,其value_type是pair型別:

  • 對迭代器進行解引用將獲得一個pair物件,它的first成員存放鍵,為const,而second成員存放值。

map<string,int>::iterator map_it=word_count.begin();//定義一個迭代器,指向word_count的第一個元素
cout<<map_it->first;//輸出第一個位置上的值--鍵
cout<<" "<<map_it->second;//輸出值
map_it->first = "new key";//錯誤!!!因為鍵值是const型別的
++map_it->second;//通過迭代器修改值

2、map容器額外定義的類型別名(typedef)

  • map類額外定義了兩種型別:key_type、mapped_type,以獲得鍵或值的型別。對於word_count,其key_type是string型別,而mapped_type是int型。如同順序容器一樣(9.3.1),可使用作用域操作符來獲取型別成員,如 map

三、給map新增元素

  • 定義了map容器後,下一步工作就是在容器中新增鍵—-值元素對,可以使用insert 成員實現,或者,先用下標操作符獲取元素,然後給獲取的元素賦值。在這種情況下,一個給定的鍵只能對應與一個元素。

四、使用下標訪問map物件

  • 使用下標訪問map與使用下標訪問陣列或vector的行為截然不同:用下標訪問不存在的元素將導致在map容器中新增一個新的元素,它的鍵即為該下標值。

  • 如同其他下標操作符一樣,map的下標也使用索引(鍵)來獲取該鍵所關聯的值。如果鍵已經在容器中,則map的下標運算與vector的下標運算行為相同:返回該鍵所關聯的值。

  • 只有在所查詢的鍵不存在時,map容器才為該建立一個新的元素,並將它插入到此map物件中。此時,所關聯的值採用值初始化:類型別的元素用預設建構函式初始化,而內建型別的元素則初始化為0

map<string , int> word_count;//空的map容器
word_count["Anna"]=1;
  • 上述程式碼發生瞭如下的事情:

  • 在word_count 中查詢鍵為Anna 的元素,沒有找到

  • 將一個新的鍵—值對插入到word_count中,它的鍵是const sring型別的物件,儲存Anna。而它的值則採用值初始化,這就意味著在本例中值為 0

  • 將這個新的鍵—值對插入到word_count中。

  • 讀取新插入的元素,並將它的值賦為1.

//習題 10.10
map<int,int> m;//首先建立一個空的map容器m,然後在m中增加一個鍵為0的元素,並將其賦值為1.
m[0]=1;

vector<int> v;//空的容器。
v[0]=1;//錯誤!!!vector不能通過下標進行初始化!!只能通過push_back,insert 等幻術增加元素。

1、下標操作符返回值的使用

  • 通常來說,下標操作符返回左值。它返回的左值是特定鍵所關聯的值。

  • 有別於vector或string型別,map下標操作符返回的型別與對map迭代器進行解引用獲得的型別不相同。

  • 顯然,map迭代器返回value_type型別的值—–包括const key_type 和mapped_type型別成員的pair物件;下標操作符返回一個mapped_type型別的值。

cout<<word_count["Anna"];//返回1
++word_count["Anna"];
cout<<word_count["Anna"];//返回2

2、下標行為的程式設計意義

  • 對於map容器,如果下標所表示的鍵在容器中不存在,咋新增新元素,這一特性可使程式設計師簡練:
map<string,int> word_count;
string word;
while(cin>>word)
  ++word_count[word];
//這段程式用來記錄每個單詞出現的次數。while迴圈每次從標準輸入中讀入一個單詞,如果這是新的單詞,則在word_count中新增以該單詞為索引的新元素。同時將它的值初始化為0、然後其值立即加1,所以每次在map中新增新元素時,所統計的出現次數正好從1開始。
//習題 10.9

#include <iostream>
#include<vector>
#include<string>
#include<map>
using namespace std;
int main()
{
  map<string,int> map_count;
  string  word;
  while(cin>>word)
      ++map_count[word];
for(map<string,int>::iterator iter=map_count.begin();iter!=map_count.end();++iter)
     {
     cout<<(*iter).first<<endl;//通過點運算子
     cout<<iter->second<<endl;//結果和(*iter).second一樣
     }
    return 0;
}