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

来自cppreference.com
< cpp‎ | named req


 
 
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 无序关联容器类
aX 类型的值
a2 一个与 X节点兼容 的类型的值
b 类型为 Xconst X 的值
a_uniqX 支持唯一键时,X 类型的值
a_eqX 支持等价键时,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, q2a 的合法常量迭代器
q, q1a 的合法且可解引用的常量迭代器
ra 的合法且可解引用的迭代器
[q1q2)a 的合法范围
ilstd::initializer_list<value_type> 类型的值
tX::value_type 类型的值
kkey_type 类型的值
hfhasherconst hasher 类型的值
eqkey_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
nsize_type 类型的值
zfloat 类型的值
nh(C++17 起)X::node_type 类型的右值

[编辑]成员类型

名字类型要求注解
X::key_typeKey
X::mapped_typeTstd::unordered_mapstd::unordered_multimap
X::value_typeKeystd::unordered_setstd::unordered_multisetX可擦除(Erasable)
std::pair<const Key, T>std::unordered_mapstd::unordered_multimapX可擦除(Erasable)
X::hasherHash散列(Hash)
X::key_equalPred可复制构造(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 = bX&容器(Container) ;复制哈希函数、谓词和最大负载因子 平均为与 b.size() 成线性,最坏 O(N2)
a = ilX&value_type 满足可复制插入(CopyInsertable) X可复制赋值(CopyAssignable) 使用 [il.begin()il.end()) 赋值给 aa 的所有元素都或被赋值或被销毁 平均为与 li.size() 成线性,最坏 O(N2)
b.hash_function()hasherb 的散列函数 常数
b.key_eq()key_equalb 的键相等性谓词 常数
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)iteratorvalue_type 满足从 args可就位构造(EmplaceConstructible) X插入一个使用 std::forward<Args>(args)... 构造的 value_type 类型的对象 t指向新插入元素的迭代器 平均 O(1),最坏 O(a_eq.size())
a.emplace_hint(p, args)iteratorvalue_type 满足从 args可就位构造(EmplaceConstructible) Xa.emplace(
  std::forward<Args>(args)...)
指向具有与新插入元素等价的键的元素的迭代器。const_iteratorp 是一个提示,指向搜索应该开始的位置。允许实现忽略提示 平均 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) Xa.insert(t)。迭代器 p 是一个提示,指向搜索应该开始的位置。允许实现忽略提示 指向键与 t 相等的元素的迭代器 平均 O(1),最坏 O(a.size())
a.insert(i, j)voidvalue_type 满足从 *i可就位构造(EmplaceConstructible) Xij 都不是 a 的迭代器 对于 [ij) 中的每个元素 ta.insert(t)平均 O(N),其中 Nstd::distance(i, j),最坏 O((a.size()+1))
a.insert_range(rg)
(C++23 起)
voidvalue_type 满足从 *ranges::begin(rg)可就位构造(EmplaceConstructible) Xrga 不重叠 对于 rg 中的每个元素 ta.insert(t)平均 O(N),其中 Nranges::distance(rg),最坏 O((a.size()+1))
a.insert(il)a.insert(il.begin(), il.end())
a_uniq.insert(nh)
(C++17 起)
insert_return_typenh 为空,或

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 起)
iteratornh 为空,或

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 起)
iteratornh 为空,或

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 起)
voida.get_allocator()
==
a2.get_allocator()
a2} 中提取该元素}。确保:指代被传输 a2 元素的指针和引用仍指代相同的这些元素,但将作为 a 的成员。指代已传输元素的迭代器和指代 a 的所有迭代器都将失效,但指向 a2 中剩余元素的迭代器将保持有效 平均 O(N),其中 Na2.size(),最坏 O((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()truea.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_typeb 包含的桶数 常数
b.max_bucket_count()size_typeb 可以包含的存储桶数量的上限 常数
b.bucket(k)size_typeb.bucket_count()>0如果存在任何具有等价于 k 的键的元素,则为在其中找到此类元素的桶的索引。返回值在 [0b.bucket_count())常数
a_tran.bucket(ke)size_typea_tran.
bucket_count()>0
如果存在任何具有等价于 ke 的键的元素,则为在其中找到此类元素的桶的索引。返回值必然在 [0a_tran.bucket_count()) 范围内 常数
b.bucket_size(n)size_typen 在范围 [0b.bucket_count())nth 桶中的元素数量 O(b.bucket_size(n))
b.begin(n)local_iterator;对于常量 bconst_local_iteratorn 在范围 [0b.bucket_count())指向桶中第一个元素的迭代器。如果桶是空的,则 b.begin(n)== b.end(n)常数
b.end(n)local_iterator;对于常量 bconst_local_iteratorn 在范围 [0b.bucket_count())迭代器,它是桶的末尾后值 常数
b.cbegin(n)const_local_iteratorn 在范围 [0b.bucket_count())指向桶中第一个元素的迭代器。如果桶是空的,则 b.cbegin(n)== b.cend(n)常数
b.cend(n)const_local_iteratorn 在范围 [0b.bucket_count())迭代器,它是桶的末尾后值 常数
b.load_factor()float每个桶的平均元素数量 常数
b.max_load_factor()float容器尝试保持负载系数小于或等于的正数。容器根据需要自动增加桶的数量,以将负载系数保持在该数值以下 常数
a.max_load_factor(z)voidz 为正。可以使用 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 重散列后负载系数只能严格小于最大负载系数 可以等于最大负载系数
close