??關(guān)聯(lián)容器有三個(gè)額外的類型別名:key_type盒刚、mapped_type郁季、value_type美侦。
set<string>::value_type v1; //v1是一個(gè)string
set<string>::key_type v2; //v1是一個(gè)string
map<string, int>::value_type v3; //v3是一個(gè)pair<const string,int>
map<string, int>::key_value v4; //v4是一個(gè)string
map<string, int>::mapped_type v5; //v5是一個(gè)int
關(guān)聯(lián)容器迭代器
??當(dāng)解引用一個(gè)關(guān)聯(lián)容器迭代器時(shí)镜会,我們會(huì)得到一個(gè)類型為容器value_type的值的引用虑稼。對(duì)map而言琳钉,value_type是一個(gè)pair類型,其first成員保存const的關(guān)鍵字蛛倦,second成員保存值:
//獲得指向word_count中一個(gè)元素的迭代器
auto map_it = word_count.begin();
//*map_it是指向一個(gè)pair<const string,size_t>對(duì)象的引用
cout << map_it->first; //打印此元素的關(guān)鍵字
cout << " " << map_it->second; //打印此元素的值
map_it->first = "new key"; //錯(cuò)誤:關(guān)鍵字是const的
++map_it->second; //正確:我們可以通過迭代器改變?cè)?
??set的迭代器是const的
??雖然set類型同時(shí)定義了iterator和const_iterator類型歌懒,但兩種類型都只允許只讀訪問set中的元素。
??遍歷關(guān)聯(lián)容器
??map和set都支持begin和end操作溯壶。我們可以用它們來進(jìn)行遍歷容器及皂。
//獲得一個(gè)指向首元素的迭代器
auto map_it = word_count.cbegin();
//比較當(dāng)前迭代器和尾后迭代器
while (map_it != word_count.cend()) {
//解引用迭代器甫男,打印關(guān)鍵字-值對(duì)
cout << map_it->first << " occurs"
<< map_it->second << " times" << endl;
++map_it; //遞增迭代器,移動(dòng)到下一個(gè)元素
}
??關(guān)聯(lián)容器和算法
??我們通常不對(duì)關(guān)聯(lián)容器使用泛型算法验烧,關(guān)鍵字是const這一特性意味著不能將關(guān)聯(lián)容器傳遞給修改或重排容器元素的算法板驳。在實(shí)際編程中,如果我們真要對(duì)一個(gè)關(guān)聯(lián)容器使用算法碍拆,要么是將它作一個(gè)源序列若治,要么當(dāng)作一個(gè)目的位置。
添加元素
??關(guān)聯(lián)容器的insert成員向容器中添加一個(gè)元素或一個(gè)元素范圍倔监。由于map和set包含不重復(fù)的關(guān)鍵字直砂,因此插入一個(gè)已存在的元素對(duì)容器沒有任何影響:
vector<int> ivec = { 2,4,6,8,2,4,6,8 }; //ivec有8個(gè)元素
set<int> set2; //空集合
set2.insert(ivec.cbegin(), ivec.cend()); //set2有4個(gè)元素
set2.insert({ 1,3,5,7,1,3,5,7 }); //set2現(xiàn)在有8個(gè)元素
??insert有兩個(gè)版本,分別接受一對(duì)迭代器浩习,或是一個(gè)初始化器列表静暂。
??向map添加元素
??對(duì)一個(gè)map進(jìn)行insert操作時(shí),必須記住元素類型是pair谱秽。
//向word_count插入word的4種方法
word_count.insert({ word,1 });
word_count.insert(make_pair(word, 1));
word_count.insert(pair<string, size_t>(word, 1));
word_count.insert(map<string, size_t>::value_type(word, 1));
??檢測(cè)insert的返回值
??insert的返回值依賴于容器類型和參數(shù)洽蛀。對(duì)于不包含重復(fù)關(guān)鍵字的容器,添加單一元素的insert和emplace版本返回一個(gè)pair疟赊,pair的first成員是一個(gè)迭代器郊供,指向具有給定關(guān)鍵字的元素;second成員是一個(gè)bool值近哟,指出元素是插入成功還是已經(jīng)存在于容器中驮审。
??向multiset和multimap添加元素
??由于multi容器中的關(guān)鍵字不必唯一,在這些類型上調(diào)用insert總會(huì)插入一個(gè)元素:
multimap<string, string> authors;
//插入第一個(gè)元素吉执。關(guān)鍵字為Barth,John
authors.insert({ "Barth,John","Sot-Weed Factor" });
//正確:添加第二個(gè)元素疯淫,關(guān)鍵字也是Barth,John
authors.insert({ "Barth,John","Lost in the Funhouse" });
刪除元素
??關(guān)聯(lián)容器定義了三個(gè)版本的erase戳玫,與順序容器一樣熙掺,我們可以通過傳遞給erase一個(gè)迭代器或一對(duì)迭代器來刪除一個(gè)元素或者一個(gè)元素范圍。關(guān)聯(lián)容器還提供一個(gè)額外的erase操作咕宿,它接受一個(gè)key_type參數(shù)币绩。此版本刪除所有匹配給定關(guān)鍵字的元素,返回實(shí)際刪除的元素的數(shù)量:
//刪除一個(gè)關(guān)鍵字府阀,返回刪除的元素?cái)?shù)量
if (word_count.erase(removal_word))
cout << "ok: " << removal_word << " removed\n";
else cout << "oops: " << removal_word << " not found!\n";
map的下標(biāo)操作
??map和unordered_map容器提供了下標(biāo)運(yùn)算符和一個(gè)對(duì)應(yīng)的at函數(shù)缆镣。set類型不支持下標(biāo)。
map<string, size_t> word_count; //empty map
//插入一個(gè)關(guān)鍵字為Anna的元素试浙,關(guān)聯(lián)值進(jìn)行值初始化费就,然后將1賦予它
word_count["Anna"] = 1;
??使用下標(biāo)運(yùn)算符可能插入一個(gè)新元素,我們只可以對(duì)非const的map使用下標(biāo)操作川队。
??使用下標(biāo)操作的返回值
??map的下標(biāo)元素符與我們用過的其他下標(biāo)運(yùn)算符的另一個(gè)不同之處是其返回類型力细。當(dāng)對(duì)一個(gè)map進(jìn)行下標(biāo)操作時(shí),會(huì)獲得一個(gè)mapped_type對(duì)象固额;但當(dāng)解引用一個(gè)map迭代器時(shí)眠蚂,會(huì)得到一個(gè)value_type對(duì)象。如果關(guān)鍵字還未在map中斗躏,下標(biāo)運(yùn)算符會(huì)添加一個(gè)新元素逝慧。
訪問元素
??關(guān)聯(lián)容器提供多種查找一個(gè)指定元素的方法,例如find和count啄糙。
set<int> iset = { 0,1,2,3,4,5,6,7,8,9 };
iset.find(1); //返回一個(gè)迭代器笛臣。指向key==1的元素
iset.find(11); //返回一個(gè)迭代器,其值等于iset.end()
iset.count(1); //返回1
iset.count(11); //返回0
??在multimap和multiset中查找元素
??在容器中可能有很多元素具有給定的關(guān)鍵字隧饼,如果一個(gè)multimap和multiset中有多個(gè)元素具有給定關(guān)鍵字沈堡,則這些元素在容器中會(huì)相鄰存儲(chǔ)。燕雁。
string search_item("Alain de Botton"); //要查找的作者
auto entries = authors.count(search_item); //元素的數(shù)量
auto iter = authors.find(search_item); //此作者的第一本書
//用一個(gè)循環(huán)查找此作者的所有著作
while (entries) {
cout << iter->second << endl; //打印每個(gè)題目
++iter; //前進(jìn)到下一本書
--entries; //記錄已經(jīng)打印了 多少本書
}
??一種不同的诞丽,面向迭代器的解決方法
??我們還可以用lower_bound和upper_bound來解決此問題。這兩個(gè)操作接受一個(gè)關(guān)鍵字拐格,返回一個(gè)迭代器僧免。如果關(guān)鍵字在容器中,lower_bound返回迭代器將指向第一個(gè)具有給定關(guān)鍵字的元素捏浊,而upper_bound返回的迭代器則指向最后一個(gè)匹配給定關(guān)鍵字的元素之后的位置懂衩。如果不在multimap中,則lower_bound和upper_bound會(huì)返回相等的迭代器金踪,指向一個(gè)不影響排序的關(guān)鍵字插入位置浊洞。
//authors和search_item的定義。與前面的程序一樣
//beg和end表示對(duì)應(yīng)此作者的元素的范圍
for (auto beg = authors.lower_bound(search_item),
end = authors.upper_bround(search_item);
beg != end; ++beg)
cout << beg->second << endl; //打印每個(gè)題目
??equa_range函數(shù)
??解決此問題的最后一種方法是三種方法中最直接的:直接調(diào)用equal_range即可热康。此函數(shù)接受一個(gè)關(guān)鍵字沛申,返回一個(gè)迭代器pair。若關(guān)鍵字存在姐军,則第一個(gè)迭代器指向第一個(gè)與關(guān)鍵字匹配的元素铁材,第二個(gè)迭代器指向最后一個(gè)匹配元素的位置,若未找到元素奕锌,則兩個(gè)迭代器都指向關(guān)鍵字可以插入的位置著觉。
//authors和search_item的定義。與前面的程序一樣
//pos保存迭代器對(duì)惊暴,v表示與關(guān)鍵字匹配的元素范圍
for (auto pos = authors.equal_range(search_item);
pos.first != pos.second; ++pos.first)
cout << pos.first->second << endl; //打印每個(gè)題目