C++ 具名要求:关联容器 (AssociativeContainer)
關聯容器 (AssociativeContainer) 是提供基於鍵的快速對象查找的容器 (Container) 。
對於每個鍵都只能包含最多一個元素的關聯容器支持唯一鍵,其他關聯容器支持等價鍵。
要求
Legend | |
X
|
一種關聯容器類 |
T
|
X 的元素類型
|
A
|
X 的分配器類型:若存在則為 X::allocator_type,否則為 std::allocator<X::value_type>
|
a
|
X 類型的值
|
a2
|
Y 類型(其節點句柄與X 兼容)的值
|
b
|
X 或 const X 類型的值
|
u
|
所要聲明的變量名字 |
a_uniq
|
X 類型的值(X 支持唯一鍵)
|
a_eq
|
X 類型的值(X 支持等價鍵)
|
a_tran
|
X 或 const X 類型的值(當存在類型 X::key_compare::is_transparent 時)
|
i, j
|
指代可以隱式轉換到 X::value_type 的元素的老式輸入迭代器 (LegacyInputIterator)
|
[i, j)
|
有效範圍 |
rg(C++23 起) |
R 類型(實現 container-compatible-range<value_type>)的值
|
p
|
到 a 的有效常量迭代器
|
q
|
到 a 的有效可解引用常量迭代器
|
r
|
到 a 的有效可解引用迭代器
|
q1, q2
|
表示 a 中的有效範圍的常量迭代器
|
il
|
std::initializer_list<X::value_type> 類型的對象
|
t
|
X::value_type 類型的值
|
k
|
X::key_type 類型的值
|
c
|
X::key_compare 或 const X::key_compare 類型的值
|
kl
|
使得 a 以 c(x, kl) 劃分的值,其中 x 是 a 中的元素 e 的鍵
|
ku
|
使得 a 以 !c(ku, x) 劃分的值,其中 x 是 a 中的元素 e 的鍵
|
ku
|
使得 a 以 c(x, ke) 和 !c(ke, x) 劃分的值,其中 c(x, ke) 意味着 !c(ke, x),並且 x 是 a 中的元素 e 的鍵
|
kx(C++23 起) |
滿足以下條件的值:
|
m
|
具有可轉換到 A 的類型的分配器
|
nh
|
X::node_type 類型的非 const 右值
|
滿足以下條件的類型 X 滿足關聯容器 (AssociativeContainer) :
- 類型
X滿足容器 (Container) (C++11 前)知分配器容器 (AllocatorAwareContainer) (C++11 起), - 它以類型
Key和在Key類型的元素上引入嚴格弱序的排序關係的Compare參數化- 另外,std::map 和 std::multimap 會將一個任意映射類型
T關聯到Key。 Compare類型的對象被稱為X類型的容器的比較對象。
- 另外,std::map 和 std::multimap 會將一個任意映射類型
- 下列表達式必須對所有關聯容器有效並具有所指定的效果:
類型
| 名稱 | 類型 | 要求 |
|---|---|---|
key_type
|
Key
|
|
mapped_type
|
T(僅限 std::map 和 std::multimap)
|
|
value_type
|
|
從 X 可擦除 (Erasable)
|
key_compare
|
Compare
|
可複製構造 (CopyConstructible) |
value_compare
|
|
二元謂詞 (BinaryPredicate) |
node_type
|
使得公開嵌套類型與 X 中對應類型相同的節點句柄類模板特化
|
成員函數與運算符
| 表達式 | 結果 | 前條件 | 效果 | 返回 | 複雜度 |
|---|---|---|---|---|---|
X(c)
|
構造空容器。以 c 的副本作為比較對象
|
常數 | |||
X u = X();X u;
|
X::key_compare 滿足可默認構造 (DefaultConstructible) 的規定
|
構造空容器。以 Compare() 作為比較對象
|
常數 | ||
X(i, j, c)
|
X::value_type 從 *i 可就位構造 (EmplaceConstructible) 到 X
|
構造空容器並向其中插入範圍 [i, j) 中的元素;以 c 作為比較對象
|
通常是 N·log(N),其中 N 的值為 std::distance(i, j);或者在 [i, j) 根據 value_comp() 有序時成線性
| ||
X(i, j)
|
X::key_compare 滿足可默認構造 (DefaultConstructible) 的規定。X::value_type 從 *i 可就位構造 (EmplaceConstructible) 到 X
|
構造空容器並向其中插入範圍 [i, j) 中的元素;以 Compare() 作為比較對象
|
|||
X(from_range, rg, c)(C++23 起) |
value_type 從 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) 到 X
|
構造空容器並向其中插入 rg 中的每個元素;以 c 作為比較對象
|
通常是 N·log(N),其中 N 的值為 ranges::distance(rg);或者在 rg 根據 value_comp() 有序時成線性
| ||
X(from_range, rg)(C++23 起) |
key_compare 滿足可默認構造 (DefaultConstructible) 的規定。value_type 從 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) 到 X
|
構造空容器並向其中插入 rg 中的每個元素;以 Compare() 作為比較對象
|
|||
X(il, c)
|
X(il.begin(), il.end(), c)
|
||||
X(il)
|
X(il.begin(), il.end())
|
||||
a = il
|
X&
|
value_type 可複製插入 (CopyInsertable) 到 X 且可複製賦值 (CopyAssignable)
|
將範圍 [il.begin(), il.end()) 賦給 a。a 的所有現存元素要麼被賦值要麼被銷毀
|
通常是 N·log(N),其中 N 的值為 il.size() + a.size();或者在 [il.begin(), il.end()) 根據 value_comp() 有序時成線性
| |
b.key_comp()
|
X::key_compare
|
構造 a 時提供的比較對象
|
常數 | ||
b.value_comp()
|
X::value_compare
|
從比較對象構造出的 value_compare 類型的對象
|
常數 | ||
a_uniq.emplace(args)
|
std::pair<iterator,bool>
|
value_type 以 args 可就位構造 (EmplaceConstructible) 到 X
|
當且僅當容器中不存在元素帶有與 t 的鍵等價的鍵時,插入一個以 std::forward<Args>(args)... 構造的 value_type 對象 t
|
當且僅當發生插入時,所返回對偶的 bool 組分為 true,而對偶的迭代器組分指向帶有與 t 的鍵等價的鍵的元素
|
對數 |
a_eq.emplace(args)
|
iterator
|
value_type 以 args 可就位構造 (EmplaceConstructible) 到 X
|
插入一個以 std::forward<Args>(args)... 構造的 value_type 對象 t。如果 a_eq 中存在包含等價於 t 的元素範圍,則 t 被插入到這個範圍末尾
|
指向新插入元素的迭代器 | 對數 |
a.emplace_hint(p, args)
|
iterator
|
等價於
|
指向帶有與新插入元素等價的鍵的元素的迭代器 | 通常是對數,但當於緊接 p 之前插入元素時是均攤常數
| |
a_uniq.insert(t)
|
std::pair<iterator,bool>
|
如果 t 是非 const 右值,則 value_type 可移動插入 (MoveInsertable) 到 X;否則 value_type 可複製插入 (CopyInsertable) 到 X
|
當且僅當容器中不存在帶有與 t 的鍵等價的鍵的元素時,插入 t
|
當且僅當發生插入時,所返回對偶的 bool 組分為 true,而對偶的 iterator 組分指向帶有與 t 的鍵等價的鍵的元素
|
對數 |
a_eq.insert(t)
|
iterator
|
如果 t 是非 const 右值,則 value_type 可移動插入 (MoveInsertable) 到 X;否則 value_type 可複製插入 (CopyInsertable) 到 X
|
插入 t 並返回指向新插入元素的迭代器。如果 a_eq 中存在包含等價於 t 的元素的範圍,則 t 被插入到這個範圍末尾
|
對數 | |
a.insert(p, t)
|
iterator
|
如果 t 是非 const 右值,則 value_type 可移動插入 (MoveInsertable) 到 X;否則 value_type 可複製插入 (CopyInsertable) 到 X
|
當且僅當帶有唯一鍵的容器中不存在帶有與 t 的鍵等價的鍵的元素時,插入 t;帶有等價鍵的容器總是插入 t。t 被插入到儘可能靠近緊接 p 之前的位置
|
指向帶有與 t 的鍵等價的鍵的元素的迭代器
|
通常是對數,但當於緊接 p 之前插入 t 時是均攤常數
|
a.insert(i, j)
|
void
|
value_type 以 *i 可就位構造 (EmplaceConstructible) 到 X。i 和 j 都不是 a 中的迭代器
|
對於範圍 [i, j) 中的各個元素,當且僅當帶有唯一鍵的容器中不存在帶有與此元素的鍵等價的鍵的元素時插入該元素;帶有等價鍵的容器總是插入該元素
|
N·log(a.size() + N),其中 N 的值為 std::distance(i, j)
| |
a.insert_range(rg)(C++23 起) |
void
|
value_type 以 *ranges::begin(rg) 可就位構造 (EmplaceConstructible) 到 X。rg 和 a 不重疊
|
對於 rg 中的各個元素,當且僅當帶有唯一鍵的容器中不存在帶有與此元素的鍵等價的鍵的元素時插入該元素;帶有等價鍵的容器總是插入該元素
|
N·log(a.size() + N), 其中 N 的值為 ranges::distance(rg)
| |
a.insert(il)
|
a.insert(il.begin(), il.end())
|
||||
a_uniq.insert(nh)
|
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() 等價的鍵的元素
|
對數 |
a_eq.insert(nh)
|
iterator
|
nh 為空,或者
|
nh 為空時無效果並返回 a_eq.end()。否則,插入 nh 擁有的元素並返回指向新插入元素的迭代器。如果 a_eq 中存在包含具有等價於 nh.key() 的鍵的元素的範圍,則在這個範圍末尾插入元素。保證:nh 為空
|
對數 | |
a.insert(p, nh)
|
iterator
|
nh 為空,或者
|
nh 為空時無效果並返回 a.end()。否則,當且僅當具有唯一鍵的容器中不存在具有與 nh.key() 等價的鍵的元素時,插入 nh 擁有的元素;具有等價鍵的容器總是插入 nh 擁有的元素。在儘可能靠近緊接 p 之前的位置插入元素。保證:nh 當插入成功時為空,當插入失敗時不改變
|
指向帶有與 nh.key() 等價的鍵的元素的迭代器
|
通常是對數,但當於緊接 p 之前插入元素時是均攤常數
|
a.extract(k)
|
node_type
|
移除容器中第一個帶有與 k 等價的鍵的元素
|
若找到則為擁有該元素的 node_type,否則為空 node_type
|
log(a.size())
| |
a_tran.extract(kx)(C++23 起) |
node_type
|
移除容器中第一個帶有鍵 r 使得 !c(r, kx) && !c(kx, r) 為 true 的元素
|
若找到則為擁有該元素的 node_type,否則為空 node_type
|
log(a_tran.size())
| |
a.extract(q)
|
node_type
|
移除 q 所指向的元素
|
擁有該元素的 node_type
|
均攤常數 | |
a.merge(a2)
|
void
|
a.get_allocator()==a2.get_allocator()
|
嘗試提取 a2 中的各個元素,並使用 a 的比較對象將其插入 a。在具有唯一鍵的容器中,如果 a 中存在某個元素帶有與 a2 中某個元素的鍵等價的鍵,則不從 a2 提取這個元素。保證:指向被轉移的 a2 元素的指針和引用,指代已作為 a 成員的相同元素。指代被轉移元素的迭代器繼續指代它們的元素,但它們現在表現為 a 而非 a2 中的迭代器。拋出:除非比較對象拋出異常,否則無拋出
|
N·log(a.size() + N),其中 N 的值為 a2.size()
| |
a.erase(k)
|
size_type
|
擦除容器中所有帶有等價於 k 的鍵的元素
|
被擦除的元素數量 | log(a.size())+ a.count(k)
| |
a_tran.erase(kx)(C++23 起) |
size_type
|
擦除容器中所有帶有鍵 r 使得 !c(r, kx) && !c(kx, r) 為 true 的元素
|
被擦除的元素數量 | log(a_tran.size())+ a_tran.count(kx)
| |
a.erase(q)
|
iterator
|
擦除 q 指向的元素
|
指向元素被擦除前緊跟 q 之後的元素的迭代器。若不存在這種元素則返回 a.end()
|
均攤常數 | |
a.erase(r)
|
iterator
|
擦除 r 指向的元素
|
指向元素被擦除前緊跟 r 之後的元素的迭代器。若不存在這種元素則返回 a.end()
|
均攤常數 | |
a.erase(q1, q2)
|
iterator
|
擦除範圍 [q1, q2) 中的所有元素
|
指向擦除任何元素之前 q2 所指向的元素的迭代器。若不存在這種元素則返回 a.end()
|
log(a.size()) + N,其中 N 的值為 std::distance(q1, q2)
| |
a.clear()
|
a.erase(a.begin(), a.end())。保證:a.empty() 為 true
|
與 a.size() 成線性
| |||
b.find(k)
|
iterator; 對常量 b 為 const_iterator
|
指向帶有等價於 k 的鍵的元素的迭代器,或未找到這種元素時為 b.end()
|
對數 | ||
a_tran.find(ke)
|
iterator; 對常量 a_tran 為 const_iterator
|
指向帶有鍵 r 使得
|
對數 | ||
b.count(k)
|
size_type
|
帶有等價於 k 的鍵的元素數量
|
log(b.size())+ b.count(k)
| ||
a_tran.count(ke)
|
size_type
|
帶有鍵 r 使得
|
log(a_tran.size())+ a_tran.count(ke)
| ||
b.contains(k)
|
bool
|
return b.find(k) != b.end();
|
|||
a_tran.contains(ke)
|
bool
|
|
|||
b.lower_bound(k)
|
iterator; 對於常量 b 為 const_iterator
|
指向第一個帶有不小於 k 的鍵的元素的迭代器,或未找到這種元素時為 b.end()
|
對數 | ||
a_tran.lower_bound(kl)
|
iterator; 對於常量 a_tran 為 const_iterator
|
指向第一個帶有鍵 r 使得 !c(r, kl) 的元素的迭代器,或未找到這種元素時為 a_tran.end()
|
對數 | ||
b.upper_bound(k)
|
iterator; 對於常量 b 為 const_iterator
|
指向第一個帶有大於 k 的鍵的元素的迭代器,或未找到這種元素時為 b.end()
|
對數 | ||
a_tran.upper_bound(ku)
|
iterator; 對於常量 a_tran 為 const_iterator
|
指向第一個帶有鍵 r 使得 c(ku, r) 的元素的迭代器,或未找到這種元素時為 a_tran.end()
|
對數 | ||
b.equal_range(k)
|
std::pair<iterator,iterator>;
對於常量 |
等價於:
|
對數 | ||
a_tran.equal_range(ke)
|
std::pair<iterator,iterator>;
對於常量 |
等價於:
|
對數 |
迭代器
關聯容器的迭代器滿足老式雙向迭代器 (LegacyBidirectionalIterator) 的要求。
對於 value_type 與 key_type 相同的關聯容器,iterator 和 const_iterator 都是常量迭代器。未指明 iterator 和 const_iterator 是否是相同類型。
關聯容器的迭代器以鍵的非降序對容器進行迭代,其中的非降序由用於構造該容器的比較所定義。就是說,給定
a,關聯容器i和j,a中的可解引用迭代器。
如果從 i 到 j 的距離為正,則 a.value_comp()(*j, *i) == false。而且,如果 a 是具有唯一鍵的關聯容器,那麼更強的條件 a.value_comp()(*i, *j) != false 也成立。
| 本節未完成 原因:Finish requirements. |
標準庫
下列標準庫容器均滿足關聯容器 (AssociativeContainer) :
| 唯一鍵的集合,按照鍵排序 (類模板) | |
| 鍵的集合,按照鍵排序 (類模板) | |
| 鍵值對的集合,按照鍵排序,鍵是唯一的 (類模板) | |
| 鍵值對的集合,按照鍵排序 (類模板) |
缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。
| 缺陷報告 | 應用於 | 出版時的行為 | 正確行為 |
|---|---|---|---|
| LWG 354 | C++98 | lower_bound 和 upper_bound 在沒找到元素時不會返回尾迭代器
|
此時它們會返回尾迭代器 |
| LWG 589 | C++98 | i 和 j 指代的元素具有 X::value_type 類型
|
那些元素可以隱式轉換到 X::value_type
|