C++ STL map 詳解


關聯式容器的一種,map 容器存儲的都是 pair 對象,也就是用 pair 類模板創建的鍵值對。其中,各個鍵值對的鍵和值可以是任意數據類型,包括 C++ 基本數據類型(int、double 等)、結構體類自定義的類型
通常情況下,map 容器中存儲的各個鍵值對都選用 string 字符串作爲鍵的類型。

map 容器

  1. 容器會自動根據各鍵值對的鍵的大小,對鍵值對做升序排序(默認)。
    即map 容器選用std::less對鍵值對升序排序。也可以手動指定 map 容器的排序規則(比如std::greater),也可以自定義排序規則。
  2. 存儲的鍵值對,鍵的值都是唯一的、獨一無二的。

一、map 容器定義

引入#include <map>
map 容器的模板定義

template < class Key,      // 指定鍵(key)的類型
    class T,        // 指定值(value)的類型
    class Compare = less<Key>,        // 指定排序規則(默認升序排列)
    class Alloc = allocator<pair<const Key,T> > // 指定分配器對象的類型
    > class map;

map 容器模板有 4 個參數,其中後 2 個參數都設有默認值。
我們只需要設定前 2 個參數的值,有些場景可能會用到第 3 個參數,但最後一個參數幾乎不會用到。

創建C++ map容器的幾種方法
map 容器的模板類中包含多種構造函數,下面就幾種常用的創建 map 容器的方法:
map 容器中存儲的鍵值對,其本質都是 pair 類模板創建的 pair 對象
map 容器的拷貝(複製)構造函數,即可成功創建一個和 myMap 完全一樣的 newMap 容器。

移動構造函數:當有臨時的 map 對象作爲參數,傳遞給要初始化的 map 容器時,此時就會調用移動構造函數。

std::map<std::string, int> myMap;                    //默認構造函數
std::map<std::string, int> myMap{ {"zhangsan",100},{"lisi",90} }; //聲明同時初始化

// pair 類模板創建
std::map<std::string, int>myMap{std::make_pair("yuwen",80),std::make_pair("shuxue",70)}; 

//調用拷貝(複製)構造函數,創建的 newMap 容器與myMap 完全一樣。
std::map<std::string, int>newMap(myMap);

// 取已建 map 容器中指定區域內的鍵值對,創建並初始化新的 map 容器
std::map<std::string, int>newMap(++myMap.begin(), myMap.end());

//手動修改了 myMap 容器爲降序排序
std::map<std::string, int, std::greater<std::string> >myMap{ {"zhangsan",100},{"lisi",90} };

//移動構造函數
std::map<std::string,int> disMap() {
    std::map<std::string, int>tempMap{ {"zhangsan",100},{"lisi",90} };
    return tempMap;
}
//調用 map 類模板的移動構造函數創建 newMap 容器
std::map<std::string, int>newMap(disMap());

注意:無論是調用複製構造函數還是調用拷貝構造函數,都必須保證這 2 個容器的類型完全一致。

二、map 容器成員方法

成員方法 功能
begin() 返回指向容器中 (已排好序)第一個鍵值對的雙向迭代器。如果 map 容器用 const 限定,則該方法返回的是 const 類型的雙向迭代器。
end() 返回指向容器 (已排好序)最後一個元素所在位置後一個位置的雙向迭代器,通常和 begin() 結合使用。如果 map 容器用 const 限定,則該方法返回的是 const 類型的雙向迭代器。
rbegin() 功能同begin() ,則該方法返回的是 const 類型的反向雙向迭代器。
rend() 功能同 end() ,則該方法返回的是 const 類型的反向雙向迭代器。
cbegin() 和 begin() 功能相同,增加了 const 屬性,不能用於修改容器內存儲的鍵值對
cend() 和 end() 功能相同,增加了 const 屬性,不能用於修改容器內存儲的鍵值對
crbegin() 和 rbegin() 功能相同,只不過在其基礎上,增加了 const 屬性,不能用於修改容器內存儲的鍵值對。
crend() 和 rend() 功能相同,只不過在其基礎上,增加了 const 屬性,不能用於修改容器內存儲的鍵值對。
find(key) 在 map 容器中查找鍵爲 key 的鍵值對,如果成功找到,則返回指向該鍵值對的雙向迭代器;反之,則返回和 end() 方法一樣的迭代器。另外,如果 map 容器用 const 限定,則該方法返回的是 const 類型的雙向迭代器。
lower_bound(key) 返回一個指向當前 map 容器中第一個大於或等於 key 的鍵值對的雙向迭代器。如果 map 容器用 const 限定,則該方法返回的是 const 類型的雙向迭代器。
upper_bound(key) 返回一個指向當前 map 容器中第一個大於 key 的鍵值對的迭代器。如果 map 容器用 const 限定,則該方法返回的是 const 類型的雙向迭代器。
equal_range(key) 該方法返回一個 pair 對象(包含 2 個雙向迭代器),其中 :
pair.first == lower_bound() 方法的返回值等價,
pair.second ==upper_bound() 方法的返回值等價。也就是說,該方法將返回一個範圍,該範圍中包含的鍵爲 key 的鍵值對(map 容器鍵值對唯一,因此該範圍最多包含一個鍵值對)。
empty() 判斷容器是否爲空:若容器爲空,則返回 true;否則 false。
size() 返回當前 map 容器中存有鍵值對的個數
max_size() 返回 map 容器所能容納鍵值對的最大個數(容器容量),不同的操作系統,其返回值亦不相同。
operator[ ] map容器重載了 [ ] 運算符,只要知道 map 容器中某個鍵值對的鍵的值,就可以向獲取數組中元素那樣,通過鍵直接獲取對應的值。
at(key) 找到 map 容器中 key 鍵對應的值,如果找不到,該函數會引發 out_of_range 異常。
insert() 向 map 容器中插入鍵值對。
erase() 刪除 map 容器指定位置、指定鍵(key)值或者指定區域內的鍵值對。
swap() 交換 2 個 map 容器中存儲的鍵值對,這意味着,操作的 2 個鍵值對的類型必須相同。
clear() 清空 map 容器中所有的鍵值對,即使 map 容器的 size() 爲 0。
emplace() 在當前 map 容器中的指定位置處構造新鍵值對。其效果和插入鍵值對一樣,但效率更高。
emplace_hint() 在本質上和 emplace() 在 map 容器中構造新鍵值對的方式是一樣的,不同之處在於,使用者必須爲該方法提供一個指示鍵值對生成位置的迭代器,並作爲該方法的第一個參數。
cout(key) 在當前 map 容器中,查找鍵爲 key 的鍵值對的個數並返回。注意,由於 map 容器中各鍵值對的鍵的值是唯一的,因此該函數的返回值最大爲 1。

小案例:

#include "stdafx.h"
#include <map>
#include <iostream>
#include <string>
#include <functional>
using namespace std;


int main()
{
	std::map<std::string, int, std::greater<std::string>> mymap;

	mymap.emplace("zhangsan", 90);
	mymap.emplace("lisi", 89);
	mymap.emplace("wangwu", 87);
	cout << "mymap.size():" << mymap.size() << endl;
	for (auto it = mymap.begin(); it != mymap.end(); it++) 
	{
		cout << it->first << " " << it->second << endl;
	}
    return 0;
}

報錯:C++ “greater”: 未聲明的標識符錯誤
引入頭文件:#include<functional> 即可解決

三、map 類元素刪除

map 類模板提供了 erase() 和 clear() 成員方法,可用來刪除容器中存儲的鍵值對。

erase() 有 3 種適用於不同實際場景需要的語法格式:

  1. 可以根據目標鍵值對位於 map 容器中的位置,實現刪除該鍵值對的目的。
    //刪除 map 容器中迭代器指定位置的鍵值對
    iterator erase (const_iterator position);
    position 爲迭代器,指向要刪除的鍵值對。同時該方法會返回一個 iterator 迭代器,其指向的是刪除鍵值對之後的那個鍵值對。(等同於 end() 成員方法返回的迭代器)

  2. 傳入目標鍵值對的 ,這個與python一樣。
    //刪除 map 容器中鍵爲 k 的鍵值對
    size_type erase (const key_type& k)
    返回值爲成功刪除的鍵值對的個數;

  3. 刪除某個指定區域內的所有鍵值對
    //刪除 map 容器中位於 [first,last) 區域內的所有鍵值對
    iterator erase (const_iterator first, const_iterator last);
    返回的迭代器將指向 map 容器最後一個鍵值對之後的位置(等同於 end() 成員方法返回的迭代器)。

小案例:

#include <iostream>
#include <map>      // map
#include <string>   // string
using namespace std;

int main() {
    map<std::string, std::string>myMap{ {"zhangsan", "今天去購物"},
                                        {"lisi", "今天去游泳"},
                                        {"wangwu", "今天去爬山"},
                                        {"zhaoliu", "今天去讀書"} };
                                        
    map<std::string, std::string>Map02{ {"zhangsan02", "今天去購物"},
                                        {"lisi02", "今天去游泳"},
                                        {"wangwu02", "今天去爬山"},
                                        {"zhaoliu02", "今天去讀書"} };

    //創建一個指向要刪除的鍵值對的迭代器(這裏指向第二個鍵值對)
    map<string, string>::iterator iter = ++myMap.begin();
    map<string, string>::iterator ret = myMap.erase(iter);     //執行刪除操作
    //輸出 erase() 方法返回的迭代器指向的鍵值對(等同於 end() 成員方法返回的迭代器)
    cout << ret->first << " " << ret->second << endl;         // wangwu 今天去爬山
    
    
    int num = myMap.erase("zhaoliu");                          //執行刪除操作
    cout << "num = " << num << endl;                           // num = 1 (成功刪除的鍵值對的個數)  


    map<string, string>::iterator first02 = Map02.begin();
    map<string, string>::iterator last02 = --Map02.end();      //--Map02.end() 向前移一位
    map<string, string>::iterator ret02 = Map02.erase(first02,last02);
    cout << ret02->first << " " << ret02->second << endl;      // zhaoliu02, 今天去讀書
    return 0;
}

void clear() 清空容器。該方法不需要傳入任何參數,也不需要接收任何返回值。
MapName.clear();

http://c.biancheng.net/view/7187.html

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