C++ 命名要求: AllocatorAwareContainer (自 C++11 起)
AllocatorAwareContainer 是一個 Container,它持有 Allocator 的例項,並在其所有成員函式中使用該例項來分配和釋放記憶體,以及在該記憶體中構造和銷燬物件(這些物件可以是容器元素、節點,或者對於無序容器,可以是桶陣列),但 std::basic_string 特化型別不使用分配器來構造/銷燬其元素(自 C++23 起)。
以下規則適用於容器構造:
- AllocatorAwareContainer 的複製建構函式透過呼叫被複制容器的分配器上的 std::allocator_traits<allocator_type>::select_on_container_copy_construction 來獲取其分配器例項。
- 移動建構函式透過從舊容器所屬的分配器進行移動構造來獲取其分配器例項。
- 所有其他建構函式都接受一個 const allocator_type& 引數。
替換分配器的唯一方法是複製賦值、移動賦值和交換。
- 僅當 std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value 為 true 時,複製賦值才會替換分配器。
- 僅當 std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value 為 true 時,移動賦值才會替換分配器。
- 僅當 std::allocator_traits<allocator_type>::propagate_on_container_swap::value 為 true 時,交換才會替換分配器。具體來說,它將透過對非成員函式 swap 的非限定呼叫來交換分配器例項,參見 Swappable。
注意:如果 `propagate_on_container_swap` 為 false,則交換兩個分配器不相等的容器的行為是未定義的。
- 訪問器 `get_allocator()` 獲取用於構造容器或透過最近的分配器替換操作安裝的分配器的副本。
目錄 |
[編輯] 要求
如果一個型別滿足 Container 並且給定以下型別和值,則它滿足 AllocatorAwareContainer 的語義和複雜性要求,如下表所示:
| 型別 | 定義 |
X
|
一個 AllocatorAwareContainer 型別 |
T
|
X 的 value_type |
A
|
X 使用的分配器型別 |
| 值 | 定義 |
| a, b | 型別為 X 的非 const 左值 |
| c | 型別為 const X 的左值 |
| t | 型別為 X 的左值或 const 右值 |
| rv | 型別為 X 的非 const 右值 |
| m | 型別為 A 的值 |
[編輯] 型別
| 名稱 | 型別 | 要求 |
|---|---|---|
| typename X::allocator_type | A
|
X::allocator_type::value_type 和 X::value_type 相同。 |
[編輯] 語句
| 語句 | 語義 | 複雜度 | |
|---|---|---|---|
| X u; X u = X(); |
前置條件 | A 是 DefaultConstructible。 |
常量 |
| 後置條件 | u.empty() 和 u.get_allocator() == A() 都為 true。 | ||
| X u(m); | 後置條件 | u.empty() 和 u.get_allocator() == m 都為 true。 | 常量 |
| X u(t, m); | 前置條件 | T 可 CopyInsertable 到 X 中。 |
線性 |
| 後置條件 | u == t 和 u.get_allocator() == m 都為 true。 | ||
| X u(rv); | 後置條件 |
|
常量 |
| X u(rv, m); | 前置條件 | T 可 MoveInsertable 到 X 中。 |
|
| 後置條件 |
| ||
[編輯] 表示式
| 表示式 | 型別 | 語義 | 複雜度 | |
|---|---|---|---|---|
| c.get_allocator() | A
|
無直接語義要求。 | 常量 | |
| a = t | X&
|
前置條件 | T 可 CopyInsertable 到 X 中並可 CopyAssignable。 |
線性 |
| 後置條件 | a == t 為 true。 | |||
| a = rv | X&
|
前置條件 | 如果分配器不會被移動賦值替換(參見上方),則 T 可 MoveInsertable 到 X 中並可 MoveAssignable。 |
線性 |
| 效果 | a 的所有現有元素要麼被移動賦值,要麼被銷燬。 | |||
| 後置條件 | 如果 a 和 rv 不指向同一物件,則 a 等於賦值之前 rv 的值。 | |||
| a.swap(b) | void | 效果 | 交換 a 和 b 的內容。 | 常量 |
[編輯] 注意
AllocatorAwareContainers 總是呼叫 std::allocator_traits<A>::construct(m, p, args) 來在 p 處構造型別為 T 的物件,使用 args,其中 m == get_allocator()。std::allocator 中的預設 construct 呼叫 ::new((void*)p) T(args)(直到 C++20)std::allocator 沒有 construct 成員,並且在構造元素時呼叫 std::construct_at(p, args)(自 C++20 起),但專門的分配器可以選擇不同的定義。
[編輯] 標準庫
所有標準庫字串型別和容器(除了 std::array 和 std::inplace_vector)都是 AllocatorAwareContainer。
| 儲存和操作字元序列 (類模板) | |
| 雙端佇列 (類模板) | |
| (C++11) |
單向連結串列 (類模板) |
| 雙向連結串列 (類模板) | |
| 可變大小的連續陣列 (類模板) | |
| 鍵值對集合,按鍵排序,鍵唯一 (類模板) | |
| 鍵值對的集合,按鍵排序 (類模板) | |
| 唯一鍵的集合,按鍵排序 (類模板) | |
| 鍵的集合,按鍵排序 (類模板) | |
| (C++11) |
鍵值對的集合,按鍵雜湊,鍵是唯一的 (類模板) |
| (C++11) |
鍵值對集合,按鍵雜湊 (類模板) |
| (C++11) |
由鍵雜湊的唯一鍵集合 (類模板) |
| (C++11) |
鍵的集合,按鍵雜湊 (類模板) |
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。
| 缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
|---|---|---|---|
| LWG 2839 | C++11 | 標準容器的自移動賦值不被允許 | 允許但結果未指定 |