【C++】STL:map引數解析
如果基礎薄弱,那麼在看這篇部落格時,請先檢視map的例子。
map 是一種有序無重複的關聯容器。
關聯容器與順序容器不同,他們的元素是按照關鍵字來儲存和訪問的,而順序元素是按照它們在容器中的位置儲存和訪問的。
map儲存的是一種 key - value 的pair物件,其中 key 是關鍵字,value 是關鍵字對應的值。通過 key找到對應的 value。map中按照 key的大小升序排列pair物件。
typedef pair<const Key, T> value_type
其中key是const的,即不可以改變map中的key。
在map中定位特定的元素比 unordered_map 要慢,因為在 map中需要根據 key的大小進行順序查詢。
但是在map中允許直接選取一定範圍的元素。
map在底層通常用二叉搜尋樹實現。
模板引數的第三個 class Compare = less<Key> 是一種比較函式
通過這個比較函式,map能比較兩個不同的 key值的大小關係,及是否相等。預設採用 less<Key>, 即 Key 型別的 "<"操作符。
如果 Key型別沒有"<"操作符的定義,則需要提供一個自定義比較函式的函式指標,來作為Compare函式。
map會自動根據key進行Compare,所以如果你所使用的Key不能Compare那麼就需要自己過載運算子,或者自定義Compare類。
template < class Key, // map::關鍵字型別 class T, // map::值型別 class Compare = less<Key>, // map::關鍵字比較函式 class Alloc = allocator<pair<const Key,T> > // map::allocator類 > class map;
建構函式
(1) 預設構造: map<Key, value> m; 構造一個空的map,注意,必要時要給出模板引數中的 Compare。需要時給出 Alloc
(2) 範圍構造: map<key, value> m(iterator first, iterator last); 將迭代器[frist, last)範圍內的元素填入map中
(3) 拷貝構造: map<key, value> m(cosnt map& m2); 用m2構造m
(4) 初始化列表構造: map<key, value> m(initializer_list<value_type> il)
由於map 的 value_type 是 pair型別,所以要構造成pair作為列表,這是三種構造 pair的方式
map<key, value> m{{key k1, value v1},{k2, v2}, ...} // 通過 {}構造 pair
map<key, value> m{make_pair(key k1, value v1), make_pair(k2, v2), ...} // 通過 make_pair() 函式構造 pair
map<key, value> m{pair<key, value>(k1, v1), pair<key, value>(k2, v2), ...} // 通過型別轉換構造 pair
賦值操作符=
map& operator= (const map& x) // map賦值
map& operator= (map&& x) // 不懂
map& operator= (initializer_list<value_type> il) // 引數列表賦值
迭代器
begin, end, rbegin, rend
cbegin, cend, crbegin, crend
map 的迭代器支援 ++, -- 操作,但是不支援 +i 操作。
注意 map中是根據 key的值來排列元素的位置的,所以通過迭代器遍歷出來的結果順序,可能和插入值的順序不同。
另外對 map的迭代器解引用的結果是得到一個 pair型別的物件。它有兩個共有成員 first, second。first儲存 key的值,second 儲存value的值。
由於map的 key 是 const的,所以得到的 pair 的first 也是const 的。
成員函式
容量
empty() // 如果map 為空,返回true。否則返回 false
// bool empty() const noexcept;
size() // 返回map 中元素的大小,即 key-value 的個數
// size_type size() const noexcept;
max_size() // 返回由於儲存空間的限制,map有可能包含的最大元素數。但不保證一定能達到這個數量,有可能在中途申請空間失敗。
// size_type max_size() const noexcept;
元素訪問
操作符[] // m[k] 返回map 中 Key為 k的元素的value的引用。
// 如果 k不存在,那麼將會插入一個 key為 k的元素,並返回其預設 value。
// []操作總會將 map的大小 +1
// 注意,對於map,解引用迭代器得到 pair,操作符[]得到 value
at() // m.at(k) 返回map中Key為k的元素的value的引用。
// 如果k不存在,拋一個 out_of_range 異常。
// 使用 at 不會新增元素,不會增加 map的大小
修改
insert 插入
(1) pair<iterator, bool> insert(const pair<key, value> &val);
// 單個值插入,引數為 pair型別,first 為 key, second為 value
// 返回值也是一個 pair,first為插入後的 iterator,second 為bool型別, true表示插入成功,false 表示插入失敗
// 插入失敗是因為 map 中已經有一個 key 與輸入相同。這次插入操作對map 不會有任何影響, 失敗時返回值的 first指向已有的key-value
(2) iterator insert(const_iterator pos, const pair<key, value> &val);
// 提示值插入
// 從 pos 指定的位置開始查詢 val應該插入的位置
// 如果設定值合適,可以減少插入時做查詢的時間
(3) void insert(iterator first, iterator second);
// 範圍插入,插入[first, second)範圍內的內容
(4) void insert(initializer_list<value_type> il);
// 初始化列表插入
emplace 高效插入
和 insert的主要區別在於,insert首先構造一個臨時 value_type物件,再copy到 map中。
而emplace 是直接在map里根據引數構造 value_type物件。更高效。
pair<iterator, bool> emplace(key k, value v);
返回值與 insert情況相同。
emplace_hint 提示位置的高效插入
iterator emplace(const iterator pos, key k, value v);
從pos開始查詢應該插入的位置,其餘和 emplace相同。
erase 刪除
(1) iterator erase(const_iterator position); // 刪除迭代器指向的內容, 函式返回 NULL
(2) iterator erase(const_iterator first, const_iterator last); // 刪除迭代器範圍內的內容,函式返回NULL
(3) size_type erase(const key_type &k); // 刪除 type 為k的元素,返回刪除的數目。對於 map,成功刪除返回1,k不存在則返回0
(4) 1,2中如果迭代器無效,會產生 undefined behavior
swap 交換兩個 map物件的內容
(1) void swap(map &x)
(2) void swap(map &x1, map &x2) // 非成員過載函式
clear 清空一個容器的所有元素
void clear() noexcept;
操作
find 查詢
在map中查詢key 為 k的元素,返回指向它的迭代器。若k不存在,返回 map::end.
// iterator find(const key_type &k);
count 計數
統計map中 key為k的元素的個數,對於map,返回值不是1(存在),就是0(不存在)
// size_type count(const key_type &k) const;