C++ 具名要求:无序关联容器 (UnorderedAssociativeContainer) (C++11 起)

出自cppreference.com


 
 
C++ 具名要求
 

無序關聯容器 是提供基於鍵的快速對象查找的容器 (Container) 。 最壞情況的複雜度為線性,但平均而言大多數操作則快得多。

無序關聯容器基於以下各項參數化:KeyHash,表現為 Key 上散列函數的散列 (Hash) 函數對象;Pred,評估 Key 間的等價性的二元謂詞 (BinaryPredicate) std::unordered_mapstd::unordered_multimap 還擁有與 Key 關聯的被映射類型 T

如果兩個 Key 按照 Pred 比較為相等,那麼 Hash 必須對兩個鍵返回相同值。

如果 Hash::is_transparentPred::is_transparent 均存在且均代表類型,那麼成員函數 findcontainscountequal_range 接受異於 Key 的實參類型並期待 Hash 能以那些類型調用,而 Pred 是如 std::equal_to<> 的透明比較函數。

(C++20 起)

std::unordered_mapstd::unordered_set 能容納至多一個帶給定鍵的元素,而 std::unordered_multisetstd::unordered_multimap 能擁有帶同一鍵的多個元素(它們在迭代時必然相鄰)。

對於 std::unordered_setstd::unordered_multiset,它們的值類型與鍵類型相同,且 iteratorconst_iterator 都是常量迭代器。對於 std::unordered_mapstd::unordered_multimap,值類型是 std::pair<const Key, T>

無序關聯容器中的元素被組織到桶中,擁有相同散列值的鍵將歸於相同的桶中。 桶數在容器大小增加時增加,以保持每個桶中的平均元素數在某個確定值之下。

重散列會使迭代器失效,並可能導致元素被重排到不同的桶中,但不會使元素的引用失效。

無序關聯容器滿足知分配器容器 (AllocatorAwareContainer) 的要求。對於 std::unordered_mapstd::unordered_multimap知分配器容器 (AllocatorAwareContainer) value_type 的要求應用到 key_typemapped_type(而非到 value_type)。

要求

凡例
X 無序關聯容器類
a X 類型的值
a2 一個與 X 節點兼容 的類型的值
b 類型為 Xconst X 的值
a_uniq X 支持唯一鍵時,X 類型的值
a_eq X 支持等價鍵時,X 類型的值
a_tran 當有限定標識符 X::key_equal::is_transparentX::hasher::is_transparent 都有效且代表類型時,

Xconst X 類型的值

i, j 引用 value_type 的輸入迭代器
[ij) 合法範圍
rg (C++23 起) R 類型的值,實現 container-compatible-range<value_type>
p, q2 a 的合法常量迭代器
q, q1 a 的合法且可解引用的常量迭代器
r a 的合法且可解引用的迭代器
[q1q2) a 的合法範圍
il std::initializer_list<value_type> 類型的值
t X::value_type 類型的值
k key_type 類型的值
hf hasherconst hasher 類型的值
eq key_equalconst key_equal 類型的值
ke 值,當 r1r2a_tran 的元素的鍵時,滿足
  • eq(r1, ke) == eq(ke, r1),
  • hf(r1) == hf(ke)eq(r1, ke)true,且
  • 如果 eq(r1, ke)eq(r2, ke)eq(r1, r2) 中有兩個是 true,那麼三個都是 true
kx (C++23 起) 值,當 r1r2a_tran 的元素的鍵時,滿足
  • eq(r1, kx) == eq(kx, r1),
  • hf(r1) == hf(kx)eq(r1, kx)true
  • 如果 eq(r1, kx)eq(r2, kx)eq(r1, r2) 中有兩個是 true,那麼三個都是 true
  • kx 不能轉換到 iterator 或者 const_iterator
n size_type 類型的值
z float 類型的值
nh (C++17 起) X::node_type 類型的右值

成員類型

名字 類型 要求 註解
X::key_type Key
X::mapped_type T std::unordered_mapstd::unordered_multimap
X::value_type Key std::unordered_setstd::unordered_multisetX 可擦除 (Erasable)
std::pair<const Key, T> std::unordered_mapstd::unordered_multimapX 可擦除 (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) hasherkey_equal 滿足可默認構造 (DefaultConstructible) 構造一個至少包含 n 個桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞 O(n)
X a = X();
X a;
hasherkey_equal 滿足可默認構造 (DefaultConstructible) 構造一個具有未指定數量的桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞 常數
X(i, j, n, hf, eq) value_type 滿足從 *i 可就位構造 (EmplaceConstructible) X 構造一個至少具有 n 個桶的空容器,使用 hf 作為散列函數,使用 eq 作為鍵相等性謂詞,並向其插入 [ij) 的元素 平均 O(N)Nstd::distance(i, j)),最壞 O(N2)
X(i, j, n, hf) key_equal 滿足可默認構造 (DefaultConstructible) value_type 滿足從 *i 可就位構造 (EmplaceConstructible) X 構造一個至少具有 n 個桶的空容器,使用 hf 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 [ij) 的元素 平均 O(N)Nstd::distance(i, j)),最壞 O(N2)
X(i, j, n) hasherkey_equal 滿足可默認構造 (DefaultConstructible) value_type 滿足從 *i 可就位構造 (EmplaceConstructible) X 構造一個至少具有 n 個桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 [ij) 的元素 平均 O(N)Nstd::distance(i, j)),最壞 O(N2)
X(i, j) hasherkey_equal 滿足可默認構造 (DefaultConstructible) value_type 滿足從 *i 可就位構造 (EmplaceConstructible) X 構造一個未指定數量的桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 [ij) 的元素 平均 O(N)Nstd::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)Nstd::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)Nstd::distance(i, j)),最壞 O(N2)
X(std::from_range,
rg, n)

(C++23 起)
hasherkey_equal 滿足可默認構造 (DefaultConstructible) value_type 滿足從 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) X 構造一個至少具有 n 個桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 rg 的元素 平均 O(N)Nstd::distance(i, j)),最壞 O(N2)
X(std::from_range,
rg)

(C++23 起)
hasherkey_equal 滿足可默認構造 (DefaultConstructible) value_type 滿足從 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) X 構造一個未指定數量的桶的空容器,使用 hasher() 作為散列函數,使用 key_equal() 作為鍵相等性謂詞,並向其插入 rg 的元素 平均 O(N)Nstd::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()) 賦值給 aa 的所有元素都或被賦值或被銷毀 平均為與 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) Xij 都不是 a 的迭代器 對於 [ij) 中的每個元素 ta.insert(t) 平均 O(N),其中 Nstd::distance(i, j),最壞 O(N·(a.size() + 1))
a.insert_range(rg)
(C++23 起)
void value_type 滿足從 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) Xrga 不重疊 對於 rg 中的每個元素 ta.insert(t) 平均 O(N),其中 Nranges::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 為空,或

a_uniq.get_allocator()
==
nh.get_allocator()
true

如果 nh 為空,則無效。否則,當且僅當容器中不存在鍵等於 nh.key() 的元素時,插入 nh 擁有的元素。確保:如果 nh 為空,則 insertedfalsepositionend(),並且 node 為空。否則,如果發生插入,則 insertedtrueposition 指向插入的元素,而 node 為空;如果插入失敗,則 insertedfalsenode 具有 nh 的先前值,並且 position 指向鍵相當於 nh.key() 的元素 平均 O(1),最壞 O(a_uniq.size())
a_eq.insert(nh)
(C++17 起)
iterator nh 為空,或

a_eq.get_allocator()
==
nh.get_allocator()
true

如果 nh 為空,則無效並返回 a_eq.end()。否則,插入 nh 擁有的元素並返回指向新插入元素的迭代器。確保:nh 為空 平均 O(1),最壞 O(a_eq.size())
a.insert(q, nh)
(C++17 起)
iterator nh 為空,或

a.get_allocator()
==
nh.get_allocator()
true

如果 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),其中 Na2.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 擦除範圍 [q1q2) 內的所有元素 擦除之前緊隨所擦除元素的迭代器 平均為線性 std::distance(q1, q2),最壞 O(a.size())
a.clear() void 擦除容器中的所有元素。確保:a.empty()true a.size() 成線性
b.find(k) iterator;對於常量 bconst_iterator 指向鍵等價於 k 的元素的迭代器,或當不存在這種元素時為 b.end() 平均 O(1),最壞 O(b.size())
a_tran.find(ke)
(C++17 起)?
iterator;對於常量 a_tranconst_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>;

對於常量 bstd::pair<
const_iterator,
const_iterator>

包含鍵等於 k 的所有元素的範圍。不存在這樣的元素時返回

std::make_pair(
b.end(), b.end())

平均 O(b.count(k)),最壞 O(b.size())
a_tran.equal_range(ke)
(C++20 起)?
std::pair<
iterator,
iterator>;

對於常量 a_transtd::pair<
const_iterator,
const_iterator>

包含鍵等於 ke 的所有元素的範圍。不存在這樣的元素時返回

std::make_pair(
a_tran.end(),
a_tran.end())

平均 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 的鍵的元素,則為在其中找到此類元素的桶的索引。返回值在 [0b.bucket_count()) 常數
a_tran.bucket(ke) size_type a_tran.
bucket_count() > 0
如果存在任何具有等價於 ke 的鍵的元素,則為在其中找到此類元素的桶的索引。返回值必然在 [0a_tran.bucket_count()) 範圍內 常數
b.bucket_size(n) size_type n 在範圍 [0b.bucket_count()) nth 桶中的元素數量 O(b.bucket_size(n))
b.begin(n) local_iterator;對於常量 bconst_local_iterator n 在範圍 [0b.bucket_count()) 指向桶中第一個元素的迭代器。如果桶是空的,則 b.begin(n) == b.end(n) 常數
b.end(n) local_iterator;對於常量 bconst_local_iterator n 在範圍 [0b.bucket_count()) 迭代器,它是桶的末尾後值 常數
b.cbegin(n) const_local_iterator n 在範圍 [0b.bucket_count()) 指向桶中第一個元素的迭代器。如果桶是空的,則 b.cbegin(n) == b.cend(n) 常數
b.cend(n) const_local_iterator n 在範圍 [0b.bucket_count()) 迭代器,它是桶的末尾後值 常數
b.load_factor() float 每個桶的平均元素數量 常數
b.max_load_factor() float 容器嘗試保持負載係數小於或等於的正數。容器根據需要自動增加桶的數量,以將負載係數保持在該數值以下 常數
a.max_load_factor(z) void z 為正。可以使用 z 作為提示來更改容器的最大負載係數 常數
a.rehash(n) void 保證:

a.bucket_count() >=
a.size() / a.max_load_factor()
a.bucket_count() >= n

平均為與 a.size() 成線性,最壞 O(N2)
a.reserve(n) a.rehash(std::ceil(
n / a.max_load_factor()))

標準庫

下列標準庫容器均滿足無序關聯容器 (UnorderedAssociativeContainer)

(C++11 起)
唯一鍵的集合,按照鍵生成散列
(類模板) [編輯]
鍵的集合,按照鍵生成散列
(類模板) [編輯]
(C++11 起)
鍵值對的集合,按照鍵生成散列,鍵是唯一的
(類模板) [編輯]
鍵值對的集合,按照鍵生成散列
(類模板) [編輯]

缺陷報告

下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。

缺陷報告 應用於 出版時的行為 正確行為
LWG 2156 C++11 重散列後負載係數只能嚴格小於最大負載係數 可以等於最大負載係數