std::multimap 是標準庫中允許重複鍵值的關聯容器,底層同為紅黑樹,操作複雜度與 map 相同 (對數級)。適用於電話簿(一名多號)、DNS(多域名解析同 IP)、檔案系統硬連結等場景。本文詳細說明插入、查找、範圍存取、與 map 差異。
map 的 operator[] 單一回傳值,無法表達一鍵多值。標準庫解法:移除 operator[],改用 insert() 配合迭代器區間存取。
#include <map>
#include <string>
multimap<string, string> phonebook;
phonebook.insert(make_pair("Harry", "8225687")); // 家裡
phonebook.insert(make_pair("Harry", "555123123")); // 公司
phonebook.insert(make_pair("Harry", "2532532532")); // 手機
insert() 回傳值差異| 容器 | insert() 回傳型別 | 說明 |
|---|---|---|
multimap | iterator | 指向新插入元素,永遠成功 |
map | pair<iterator, bool> | bool 表示是否插入成功 (鍵值不重複) |
auto it = phonebook.find("Harry");
if (it != phonebook.end())
cout << "第一筆: " << it->second << endl; // 僅取得第一筆
find(k) 回傳第一個匹配鍵值的迭代器,適合「是否存在」或「取第一筆」需求。
count(k) - 統計筆數
cout << phonebook.count("Harry"); // 輸出 3
equal_range(k) - 取得完整範圍 (推薦)
typedef multimap<string, string>::const_iterator CI;
typedef pair<CI, CI> Range;
Range range = phonebook.equal_range("Harry");
for (CI it = range.first; it != range.second; ++it)
cout << it->second << endl;
// 輸出所有 Harry 的電話
lower_bound / upper_bound - 邊界迭代器lower_bound(k):第一個 ≥ k 的元素 (等同 equal_range.first)upper_bound(k):第一個 > k 的元素 (等同 equal_range.second)
// 列印所有鍵值 > "Harry" 的記錄
auto it = phonebook.upper_bound("Harry");
while (it != phonebook.end())
{
cout << it->first << " = " << it->second << endl;
++it;
}
multimap<string, string> dns; // IP → 域名
dns.insert(make_pair("213.108.96.7", "cppzone.com"));
dns.insert(make_pair("213.108.96.7", "cpluspluszone.com"));
dns.insert(make_pair("219.108.96.70", "pythonzone.com"));
dns.insert(make_pair("219.108.96.70", "python-zone.com"));
// 查詢單一 IP 的所有域名
auto range = dns.equal_range("213.108.96.7");
for (auto it = range.first; it != range.second; ++it)
cout << it->second << endl;
// cpluspluszone.com
// cppzone.com
// 列印所有 IP > 213.108.96.7 的域名
for (auto it = dns.upper_bound("213.108.96.7"); it != dns.end(); ++it)
cout << it->first << " → " << it->second << endl;
| 場景 | 選擇 | 理由 |
|---|---|---|
鍵值唯一、需 operator[] 便利存取 | map | 語法簡潔、單值語義明確 |
| 一鍵多值、需遍歷所有關聯值 | multimap | 原生支援重複鍵、equal_range 高效 |
| 需頻繁統計鍵值出現次數 | multimap | count() O(log n + k) |
| 鍵值唯一但需高效範圍查詢 | map | lower/upper_bound 同樣適用 |
operator[]:multimap 未提供,編譯錯誤insert() 永遠成功:不檢查重複,若需唯一性請用 map 或自行檢查multimap<Key, T, Compare, Alloc> 第三模板參數指定排序準則multimap 以「捨棄 operator[]」換取「原生重複鍵支援」,是處理一對多關聯的標準利器。掌握 insert/find/count/equal_range/lower_bound/upper_bound 完整介面,配合 make_pair 輔助函數,即可優雅解決電話簿、DNS、標籤系統等經典問題。