C++ 具名要求:无序关联容器 (UnorderedAssociativeContainer) (C++11 起)
無序關聯容器 是提供基於鍵的快速對象查找的容器 (Container) 。 最壞情況的複雜度為線性,但平均而言大多數操作則快得多。
無序關聯容器基於以下各項參數化:Key;Hash,表現為 Key 上散列函數的散列 (Hash) 函數對象;Pred,評估 Key 間的等價性的二元謂詞 (BinaryPredicate) 。
std::unordered_map 與 std::unordered_multimap 還擁有與 Key 關聯的被映射類型 T。
如果兩個 Key 按照 Pred 比較為相等,那麼 Hash 必須對兩個鍵返回相同值。
|
如果 |
(C++20 起) |
std::unordered_map 與 std::unordered_set 能容納至多一個帶給定鍵的元素,而 std::unordered_multiset 與 std::unordered_multimap 能擁有帶同一鍵的多個元素(它們在迭代時必然相鄰)。
對於 std::unordered_set 和 std::unordered_multiset,它們的值類型與鍵類型相同,且 iterator 和 const_iterator 都是常量迭代器。對於 std::unordered_map 與 std::unordered_multimap,值類型是 std::pair<const Key, T>。
無序關聯容器中的元素被組織到桶中,擁有相同散列值的鍵將歸於相同的桶中。 桶數在容器大小增加時增加,以保持每個桶中的平均元素數在某個確定值之下。
重散列會使迭代器失效,並可能導致元素被重排到不同的桶中,但不會使元素的引用失效。
無序關聯容器滿足知分配器容器 (AllocatorAwareContainer) 的要求。對於 std::unordered_map 與 std::unordered_multimap,知分配器容器 (AllocatorAwareContainer) 中 value_type 的要求應用到 key_type 和 mapped_type(而非到 value_type)。
要求
凡例 | |
X
|
無序關聯容器類 |
a
|
X 類型的值
|
a2
|
一個與 X 節點兼容 的類型的值
|
b
|
類型為 X 或 const X 的值
|
a_uniq
|
X 支持唯一鍵時,X 類型的值
|
a_eq
|
X 支持等價鍵時,X 類型的值
|
a_tran
|
當有限定標識符 X::key_equal::is_transparent 和 X::hasher::is_transparent 都有效且代表類型時,
為 |
i, j
|
引用 value_type 的輸入迭代器
|
[i, j)
|
合法範圍 |
rg (C++23 起)
|
R 類型的值,實現 container-compatible-range<value_type>
|
p, q2
|
a 的合法常量迭代器
|
q, q1
|
a 的合法且可解引用的常量迭代器
|
r
|
a 的合法且可解引用的迭代器
|
[q1, q2)
|
a 的合法範圍
|
il
|
std::initializer_list<value_type> 類型的值
|
t
|
X::value_type 類型的值
|
k
|
key_type 類型的值
|
hf
|
hasher 或 const hasher 類型的值
|
eq
|
key_equal 或 const key_equal 類型的值
|
ke
|
值,當 r1 和 r2 是 a_tran 的元素的鍵時,滿足
|
kx (C++23 起)
|
值,當 r1 和 r2 是 a_tran 的元素的鍵時,滿足
|
n
|
size_type 類型的值
|
z
|
float 類型的值
|
nh (C++17 起)
|
X::node_type 類型的右值
|
成員類型
| 名字 | 類型 | 要求 | 註解 |
|---|---|---|---|
X::key_type
|
Key
|
||
X::mapped_type
|
T
|
僅 std::unordered_map 和 std::unordered_multimap | |
X::value_type
|
Key
|
僅 std::unordered_set 和 std::unordered_multiset。X 可擦除 (Erasable)
|
|
std::pair<const Key, T>
|
僅 std::unordered_map 和 std::unordered_multimap。X 可擦除 (Erasable)
|
||
X::hasher
|
Hash
|
散列 (Hash) | |
X::key_equal
|
Pred
|
可複製構造 (CopyConstructible) ;接受兩個 Key 類型的參數,並表達等價關係的二元謂詞 (BinaryPredicate)
|
|
X::local_iterator
|
老式迭代器 (LegacyIterator) | 具有和 X::iterator 相同的類別和類型
|
可用於遍歷單個桶,但不能遍歷所有桶 |
X::const_local_iterator
|
老式迭代器 (LegacyIterator) | 具有和 X::const_iterator 相同的類別和類型
| |
X::node_type (C++17 起)
|
node-handle 類模板的特化 | 其公開嵌套類型與 X 中的對應類型相同。
|
成員函數和運算符
| 表達式 | 結果 | 前條件 | 效果 | 返回值 | 複雜度 |
|---|---|---|---|---|---|
X(n, hf, eq)
|
構造一個至少包含 n 個桶的空容器,使用 hf 作為散列函數,使用 eq 作為鍵相等性謂詞
|
O(n)
| |||
X(n, hf)
|
key_equal 滿足可默認構造 (DefaultConstructible)
|
構造一個至少包含 n 個桶的空容器,使用 hf 作為散列函數,使用 key_equal() 作為鍵相等性謂詞
|
O(n)
| ||
X(n)
|
hasher 和 key_equal 滿足可默認構造 (DefaultConstructible)
|
構造一個至少包含 n 個桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞
|
O(n)
| ||
X a = X();X a;
|
hasher 和 key_equal 滿足可默認構造 (DefaultConstructible)
|
構造一個具有未指定數量的桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞
|
常數 | ||
X(i, j, n, hf, eq)
|
value_type 滿足從 *i 可就位構造 (EmplaceConstructible) 到 X
|
構造一個至少具有 n 個桶的空容器,使用 hf 作為散列函數,使用 eq 作為鍵相等性謂詞,並向其插入 [i, j) 的元素
|
平均 O(N)(N 為 std::distance(i, j)),最壞 O(N2)
| ||
X(i, j, n, hf)
|
key_equal 滿足可默認構造 (DefaultConstructible) 。value_type 滿足從 *i 可就位構造 (EmplaceConstructible) 到 X
|
構造一個至少具有 n 個桶的空容器,使用 hf 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 [i, j) 的元素
|
平均 O(N)(N 為 std::distance(i, j)),最壞 O(N2)
| ||
X(i, j, n)
|
hasher 和 key_equal 滿足可默認構造 (DefaultConstructible) 。value_type 滿足從 *i 可就位構造 (EmplaceConstructible) 到 X
|
構造一個至少具有 n 個桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 [i, j) 的元素
|
平均 O(N)(N 為 std::distance(i, j)),最壞 O(N2)
| ||
X(i, j)
|
hasher 和 key_equal 滿足可默認構造 (DefaultConstructible) 。value_type 滿足從 *i 可就位構造 (EmplaceConstructible) 到 X
|
構造一個未指定數量的桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 [i, j) 的元素
|
平均 O(N)(N 為 std::distance(i, j)),最壞 O(N2)
| ||
X(std::from_range,rg, n, hf, eq)(C++23 起) |
value_type 滿足從 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) 到 X
|
構造一個至少具有 n 個桶的空容器,使用 hf 作為散列函數,使用 eq 作為鍵相等性謂詞,並向其插入 rg 的元素
|
平均 O(N)(N 為 std::distance(i, j)),最壞 O(N2)
| ||
X(std::from_range,rg, n, hf)(C++23 起) |
key_equal 滿足可默認構造 (DefaultConstructible) 。value_type 滿足從 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) 到 X
|
構造一個至少具有 n 個桶的空容器,使用 hf 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 rg 的元素
|
平均 O(N)(N 為 std::distance(i, j)),最壞 O(N2)
| ||
X(std::from_range,rg, n)(C++23 起) |
hasher 和 key_equal 滿足可默認構造 (DefaultConstructible) 。value_type 滿足從 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) 到 X
|
構造一個至少具有 n 個桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 rg 的元素
|
平均 O(N)(N 為 std::distance(i, j)),最壞 O(N2)
| ||
X(std::from_range,rg)(C++23 起) |
hasher 和 key_equal 滿足可默認構造 (DefaultConstructible) 。value_type 滿足從 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) 到 X
|
構造一個未指定數量的桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 rg 的元素
|
平均 O(N)(N 為 std::distance(i, j)),最壞 O(N2)
| ||
X(il)
|
X(il.begin(), il.end())
|
||||
X(il, n)
|
X(il.begin(), il.end(), n)
|
||||
X(il, n, hf)
|
X(il.begin(), il.end(), n, hf)
|
||||
X(il, n, hf, eq)
|
X(il.begin(), il.end(), n, hf, eq)
|
||||
X(b)
|
容器 (Container) ;複製散列函數、謂詞和最大負載因子 | 平均為與 b.size() 成線性,最壞 O(N2)
| |||
a = b
|
X&
|
容器 (Container) ;複製哈希函數、謂詞和最大負載因子 | 平均為與 b.size() 成線性,最壞 O(N2)
| ||
a = il
|
X&
|
value_type 滿足可複製插入 (CopyInsertable) 到 X 且可複製賦值 (CopyAssignable)
|
使用 [il.begin(), il.end()) 賦值給 a。a 的所有元素都或被賦值或被銷毀
|
平均為與 li.size() 成線性,最壞 O(N2)
| |
b.hash_function()
|
hasher
|
b 的散列函數
|
常數 | ||
b.key_eq()
|
key_equal
|
b 的鍵相等性謂詞
|
常數 | ||
a_uniq.emplace(args)
|
std::pair<iterator,bool>
|
value_type 滿足從 args 可就位構造 (EmplaceConstructible) 到 X
|
當且僅當容器中不存在具有與 t 的鍵等價的鍵的元素時,插入一個使用 std::forward<Args>(args)... 構造的 value_type 類型的對象 t
|
當且僅當發生插入時,返回的對偶的 bool 組分為 true,並且該對偶的迭代器組分指向具有的鍵等價於 t 的鍵的元素
|
平均 O(1),最壞 O(a_uniq.size())
|
a_eq.emplace(args)
|
iterator
|
value_type 滿足從 args 可就位構造 (EmplaceConstructible) 到 X
|
插入一個使用 std::forward<Args>(args)... 構造的 value_type 類型的對象 t
|
指向新插入元素的迭代器 | 平均 O(1),最壞 O(a_eq.size())
|
a.emplace_hint(p, args)
|
iterator
|
value_type 滿足從 args 可就位構造 (EmplaceConstructible) 到 X
|
a.emplace(std::forward<Args>(args)...)
|
指向具有與新插入元素等價的鍵的元素的迭代器。const_iterator p 是一個提示,指向搜索應該開始的位置。允許實現忽略提示
|
平均 O(1),最壞 O(a.size())
|
a_uniq.insert(t)
|
std::pair<iterator,bool>
|
如果 t 是非 const 右值,則 value_type 可移動插入 (MoveInsertable) 到 X;否則,value_type 可複製插入 (CopyInsertable) 到 X
|
當且僅當容器中不存在鍵與 t 的鍵相同的元素時,插入 t
|
返回的對偶中的 bool 組分指示是否發生插入,而 iterator 組分則指向鍵與 t 的鍵等價的元素
|
平均 O(1),最壞 O(a_uniq.size())
|
a_eq.insert(t)
|
iterator
|
如果 t 是非 const 右值,則 value_type 可移動插入 (MoveInsertable) 到 X;否則,value_type 可複製插入 (CopyInsertable) 到 X
|
插入 t
|
指向新插入元素的迭代器 | 平均 O(1),最壞 O(a_eq.size())
|
a.insert(p, t)
|
iterator
|
如果 t 是非 const 右值,則 value_type 可移動插入 (MoveInsertable) 到 X;否則,value_type 可複製插入 (CopyInsertable) 到 X
|
a.insert(t)。迭代器 p 是一個提示,指向搜索應該開始的位置。允許實現忽略提示
|
指向鍵與 t 相等的元素的迭代器
|
平均 O(1),最壞 O(a.size())
|
a.insert(i, j)
|
void
|
value_type 滿足從 *i 可就位構造 (EmplaceConstructible) 到 X,i 和 j 都不是 a 的迭代器
|
對於 [i, j) 中的每個元素 t,a.insert(t)
|
平均 O(N),其中 N 為 std::distance(i, j),最壞 O(N·(a.size() + 1))
| |
a.insert_range(rg)(C++23 起) |
void
|
value_type 滿足從 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) 到 X。rg 和 a 不重疊
|
對於 rg 中的每個元素 t,a.insert(t)
|
平均 O(N),其中 N 為 ranges::distance(rg),最壞 O(N·(a.size() + 1))
| |
a.insert(il)
|
a.insert(il.begin(), il.end())
|
||||
a_uniq.insert(nh)(C++17 起) |
insert_return_type
|
nh 為空,或
|
如果 nh 為空,則無效。否則,當且僅當容器中不存在鍵等於 nh.key() 的元素時,插入 nh 擁有的元素。確保:如果 nh 為空,則 inserted 為 false,position 為 end(),並且 node 為空。否則,如果發生插入,則 inserted 為 true,position 指向插入的元素,而 node 為空;如果插入失敗,則 inserted 為 false,node 具有 nh 的先前值,並且 position 指向鍵相當於 nh.key() 的元素
|
平均 O(1),最壞 O(a_uniq.size())
| |
a_eq.insert(nh)(C++17 起) |
iterator
|
nh 為空,或
|
如果 nh 為空,則無效並返回 a_eq.end()。否則,插入 nh 擁有的元素並返回指向新插入元素的迭代器。確保:nh 為空
|
平均 O(1),最壞 O(a_eq.size())
| |
a.insert(q, nh)(C++17 起) |
iterator
|
nh 為空,或
|
如果 nh 為空,則無效並返回 a.end()。否則,當且僅當在具有唯一鍵的容器中不存在鍵等於 nh.key() 的元素時,插入 nh 擁有的元素;始終將 nh 擁有的元素插入具有相同鍵的容器中。迭代器 q 是一個提示,指向搜索應該開始的位置。允許實現忽略提示。確保:如果插入成功,nh 為空;如果插入失敗,則保持不變
|
指向鍵等於 nh.key() 的元素的迭代器
|
平均 O(1),最壞 O(a.size())
|
a.extract(k)(C++17 起) |
node_type
|
移除容器中鍵等於 k 的元素
|
如果找到,則為擁有該元素的 node_type,否則為空 node_type
|
平均 O(1),最壞 O(a.size())
| |
a_tran.extract(kx)(C++23 起) |
node_type
|
移除容器中鍵等於 kx 的元素
|
如果找到,則為擁有該元素的 node_type,否則為空 node_type
|
平均 O(1),最壞 O(a_tran.size())
| |
a.extract(q)(C++17 起) |
node_type
|
移除 q 指向的元素
|
擁有該元素的 node_type
|
平均 O(1),最壞 O(a.size())
| |
a.merge(a2)(C++17 起) |
void
|
a.get_allocator()==a2.get_allocator()
|
a2} 中提取該元素}。確保:指代被傳輸 a2 元素的指針和引用仍指代相同的這些元素,但將作為 a 的成員。指代已傳輸元素的迭代器和指代 a 的所有迭代器都將失效,但指向 a2 中剩餘元素的迭代器將保持有效
|
平均 O(N),其中 N 為 a2.size(),最壞 O(N· (a.size() + 1))
| |
a.erase(k)
|
size_type
|
擦除鍵等於 k 的所有元素
|
擦除的元素數量 | 平均 O(a.count(k)),最壞 O(a.size())
| |
a_tran.erase(kx)(C++23 起) |
size_type
|
擦除鍵等於 kx 的所有元素
|
擦除的元素數量 | 平均 O(a_tran.count(kx)),最壞 O(a_tran.size())
| |
a.erase(q)
|
iterator
|
擦除 q 指向的元素
|
擦除之前,緊跟在 q 之後的迭代器
|
平均 O(1),最壞 O(a.size())
| |
a.erase(r)(C++17 起) |
iterator
|
擦除 r 指向的元素
|
擦除之前緊跟在 r 之後的迭代器
|
平均 O(1),最壞 O(a.size())
| |
a.erase(q1, q2)
|
iterator
|
擦除範圍 [q1, q2) 內的所有元素
|
擦除之前緊隨所擦除元素的迭代器 | 平均為線性 std::distance(q1, q2),最壞 O(a.size())
| |
a.clear()
|
void
|
擦除容器中的所有元素。確保:a.empty() 為 true
|
與 a.size() 成線性
| ||
b.find(k)
|
iterator;對於常量 b 為 const_iterator
|
指向鍵等價於 k 的元素的迭代器,或當不存在這種元素時為 b.end()
|
平均 O(1),最壞 O(b.size())
| ||
a_tran.find(ke)(C++17 起)? |
iterator;對於常量 a_tran 為 const_iterator
|
指向鍵等價於 ke 的元素的迭代器,或當不存在這種元素時為 a_tran.end()
|
平均 O(1),最壞 O(a_tran.size())
| ||
b.count(k)
|
size_type
|
鍵等於 k 的元素數量
|
平均 O(b.count(k)),最壞 O(b.size())
| ||
a_tran.count(ke)(C++17 起)? |
size_type
|
鍵等於 ke 的元素數量
|
平均 O(a_tran.count(ke)),最壞 O(a_tran.size())
| ||
b.contains(k)(C++20 起)? |
b.find(k) != b.end()
|
||||
a_tran.contains(ke)(C++20 起)? |
a_tran.find(ke) != a_tran.end()
|
||||
b.equal_range(k)
|
std::pair<iterator,iterator>;
對於常量 |
包含鍵等於 k 的所有元素的範圍。不存在這樣的元素時返回
|
平均 O(b.count(k)),最壞 O(b.size())
| ||
a_tran.equal_range(ke)(C++20 起)? |
std::pair<iterator,iterator>;
對於常量 |
包含鍵等於 ke 的所有元素的範圍。不存在這樣的元素時返回
|
平均 O(a_tran.count(ke)),最壞 O(a_tran.size())
| ||
b.bucket_count()
|
size_type
|
b 包含的桶數
|
常數 | ||
b.max_bucket_count()
|
size_type
|
b 可以包含的存儲桶數量的上限
|
常數 | ||
b.bucket(k)
|
size_type
|
b.bucket_count() > 0
|
如果存在任何具有等價於 k 的鍵的元素,則為在其中找到此類元素的桶的索引。返回值在 [0, b.bucket_count()) 中
|
常數 | |
a_tran.bucket(ke)
|
size_type
|
a_tran.bucket_count() > 0
|
如果存在任何具有等價於 ke 的鍵的元素,則為在其中找到此類元素的桶的索引。返回值必然在 [0, a_tran.bucket_count()) 範圍內
|
常數 | |
b.bucket_size(n)
|
size_type
|
n 在範圍 [0, b.bucket_count()) 內
|
nth 桶中的元素數量
|
O(b.bucket_size(n))
| |
b.begin(n)
|
local_iterator;對於常量 b 為 const_local_iterator
|
n 在範圍 [0, b.bucket_count()) 內
|
指向桶中第一個元素的迭代器。如果桶是空的,則 b.begin(n) == b.end(n)
|
常數 | |
b.end(n)
|
local_iterator;對於常量 b 為 const_local_iterator
|
n 在範圍 [0, b.bucket_count()) 內
|
迭代器,它是桶的末尾後值 | 常數 | |
b.cbegin(n)
|
const_local_iterator
|
n 在範圍 [0, b.bucket_count()) 內
|
指向桶中第一個元素的迭代器。如果桶是空的,則 b.cbegin(n) == b.cend(n)
|
常數 | |
b.cend(n)
|
const_local_iterator
|
n 在範圍 [0, b.bucket_count()) 內
|
迭代器,它是桶的末尾後值 | 常數 | |
b.load_factor()
|
float
|
每個桶的平均元素數量 | 常數 | ||
b.max_load_factor()
|
float
|
容器嘗試保持負載係數小於或等於的正數。容器根據需要自動增加桶的數量,以將負載係數保持在該數值以下 | 常數 | ||
a.max_load_factor(z)
|
void
|
z 為正。可以使用 z 作為提示來更改容器的最大負載係數
|
常數 | ||
a.rehash(n)
|
void
|
保證:
|
平均為與 a.size() 成線性,最壞 O(N2)
| ||
a.reserve(n)
|
a.rehash(std::ceil(n / a.max_load_factor()))
|
| 本節未完成 原因:考慮成員函數的要求 |
標準庫
下列標準庫容器均滿足無序關聯容器 (UnorderedAssociativeContainer) :
(C++11 起) |
唯一鍵的集合,按照鍵生成散列 (類模板) |
(C++11 起) |
鍵的集合,按照鍵生成散列 (類模板) |
(C++11 起) |
鍵值對的集合,按照鍵生成散列,鍵是唯一的 (類模板) |
(C++11 起) |
鍵值對的集合,按照鍵生成散列 (類模板) |
缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。
| 缺陷報告 | 應用於 | 出版時的行為 | 正確行為 |
|---|---|---|---|
| LWG 2156 | C++11 | 重散列後負載係數只能嚴格小於最大負載係數 | 可以等於最大負載係數 |