容器函式庫(Containers library)是類別樣板與演算法的通用集合,允許程式設計師輕鬆實作常見的資料結構,如佇列、列表與堆疊。容器類別共有 兩(直到 C++11)三(自 C++11) 種:
- 序列容器(sequence containers)、
- 關聯容器(associative containers)、
- 無序關聯容器(unordered associative containers)、
|
(C++11 起) |
每一種都設計用以支援不同的操作集合。
容器管理為其元素分配的儲存空間,並提供成員函式來存取它們,無論是直接存取還是透過迭代器(具有類似指標屬性的物件)。
大多數容器至少具有幾個共同的成員函式,並共享功能。哪種容器最適合特定應用,不僅取決於所提供的功能,還取決於其在不同工作負載下的效率。
[編輯] 序列容器
序列容器實作了可以按順序存取的資料結構。
|
|
固定大小的原地 (inplace) 連續陣列 (類別模板) [編輯] |
|
|
可調整大小的連續陣列 (類別模板) [編輯] |
|
|
可調整大小、固定容量、原地連續陣列 (類別模板) [編輯] |
|
|
重用已刪除元素記憶體的集合 (類別樣板) [編輯] |
|
|
雙端隊列 (double-ended queue) (類別模板) [編輯] |
|
|
單向鏈結串列 (類別模板) [編輯] |
|
|
雙向鏈結串列 (類別模板) [編輯] |
[編輯] 關聯容器
關聯容器實作了可以快速搜尋(複雜度為 O(log n))的排序資料結構。
|
|
唯一鍵的集合,按鍵排序 (類別樣板) [編輯] |
|
|
鍵值對(key-value pairs)的集合,按鍵排序,且鍵是唯一的 (類別樣板) [編輯] |
|
|
鍵的集合,按鍵排序 (類別樣板) [編輯] |
|
|
鍵值對的集合,按鍵排序 (類別樣板) [編輯] |
[編輯] 無序關聯容器 (自 C++11)
無序關聯容器實作了未排序(雜湊)的資料結構,可以快速搜尋(平均複雜度為 O(1),最差情況下為 O(n))。
|
|
唯一鍵的集合,按鍵雜湊 (類別範本) [編輯] |
|
|
鍵值對的集合,按鍵雜湊,鍵是唯一的 (類別範本) [編輯] |
|
|
鍵的集合,按鍵雜湊 (類別範本) [編輯] |
|
|
鍵值對的集合,按鍵雜湊 (類別範本) [編輯] |
[編輯] 容器適配器
容器適配器為序列容器提供不同的介面。
|
|
適配容器以提供堆疊(stack,LIFO 資料結構) (類別樣板) [編輯] |
|
|
適配容器以提供佇列(queue,FIFO 資料結構) (類別樣板) [編輯] |
|
|
適配容器以提供優先佇列 (類別樣板) [編輯] |
|
|
適配容器以提供按鍵排序的唯一鍵集合 (類別樣板) [編輯] |
|
|
適配兩個容器以提供按唯一鍵排序的鍵值對集合 (類別樣板) [編輯] |
|
|
適配一個容器以提供按鍵排序的鍵集合 (類別樣板) [編輯] |
|
|
適配兩個容器以提供按鍵排序的鍵值對集合 (類別樣板) [編輯] |
[編輯] 視圖 (自 C++20)
視圖提供了彈性的設施,用於與非擁有型(non-owning)元素陣列上的一維或多維視圖進行互動。
|
|
連續物件序列上的非擁有型視圖 (類別樣板) [編輯] |
|
|
多維非擁有型陣列視圖 (類別樣板) [編輯] |
[編輯] 迭代器失效
唯讀方法絕不會使迭代器或參照失效。修改容器內容的方法可能會使迭代器和/或參照失效,如下表所示。
此處,插入是指任何向容器增加一個或多個元素的方法,而刪除(erasure)是指任何從容器移除一個或多個元素的方法。
除非另有說明(無論是明確說明或是透過其他函式來定義某個函式),否則將容器作為引數傳遞給函式庫函式絕不會使指向該容器內物件的迭代器失效,也不會改變該容器內物件的值。
尾後迭代器(past-the-end iterator)值得特別提。一般來說,此迭代器會像是指向未刪除元素的一般迭代器一樣失效。因此 std::set::end 永遠不會失效,而 std::unordered_set::end 僅在重新雜湊時失效(自 C++11),std::vector::end 則總是會失效(因為它總是在被修改的元素之後),以此類推。
有一個例外:刪除 std::deque 最後一個元素的刪除操作「確實」會使尾後迭代器失效,儘管它並不是容器中被刪除的元素(甚至根本不是元素)。結合 std::deque 迭代器的一般規則,最終結果是唯一「不會」使 std::deque::end 失效的修改操作是刪除第一個元素而非最後一個元素的刪除操作。
執行緒安全
- 所有容器函式都可以由不同執行緒在不同容器上同時呼叫。更廣泛地說,C++ 標準函式庫函式不會讀取其他執行緒可存取的物件,除非這些物件可透過函式引數(包括 this 指標)直接或間接存取。
- 所有 const 成員函式都可以由不同執行緒在同一個容器上同時呼叫。此外,就執行緒安全而言,成員函式
begin()、end()、rbegin()、rend()、front()、back()、data()、find()、lower_bound()、upper_bound()、equal_range()、at() 以及(除了關聯容器外的)operator[] 的行為都視同 const(也就是說,它們也可以由不同執行緒在同一個容器上同時呼叫)。更廣泛地說,C++ 標準函式庫函式不會修改物件,除非這些物件可透過函式的非 const 引數(包括 this 指標)直接或間接存取。 - 同一個容器中的不同元素可以由不同執行緒同時修改,但 std::vector<bool> 的元素除外(例如,std::future 物件的 vector 可以從多個執行緒接收值)。
- 迭代器操作(例如遞增一個迭代器)會讀取但不會修改底層容器,並可與同一個容器上其他迭代器的操作、const 成員函式或對元素的讀取同時執行。會使任何迭代器失效的容器操作則會修改容器,不能與現有迭代器上的任何操作同時執行,即使那些迭代器並未失效。
- 同一個容器的元素可以與那些未指定會存取這些元素的成員函式同時修改。更廣泛地說,C++ 標準函式庫函式不會讀取透過其引數間接存取的物件(包括容器的其他元素),除非其規範有此要求。
- 在任何情況下,容器操作(以及演算法或任何其他 C++ 標準函式庫函式)都可以在內部平行化,只要這不改變使用者可見的結果(例如 std::transform 可以平行化,但規定按順序訪問序列中每個元素的 std::for_each 則不行)。
|
(C++11 起) |
[編輯] 函式表
註:標準並未將 std::basic_string 視為容器,但由於其相似性,其行為非常像容器。為方便起見,此處將其列為「虛擬容器(Pseudo container)」。
|
|
- C++03 中存在的函式 |
|
|
- 自 C++11 起存在的函式 |
|
|
- 自 C++17 起存在的函式 |
|
|
- 自 C++20 起存在的函式 |
|
|
- 自 C++23 起存在的函式 |
[編輯] 成員函式表
- 註:兩個不同 extract 行中的函式具有不同的意義與語法
- ↑ 例如,node_type extract(const_iterator) 或 node_type extract(Key&)
- ↑ 例如,container_type extract() &&
[編輯] 非成員函式表
|
<、<=、>、>= 與 != 運算子分別從 operator<=> 與 operator== 合成(synthesized)而來。
|
(自 C++20 起) |
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯應用於之前的 C++ 標準。
| DR |
應用於 |
出版時的行為 |
正確的行為 |
| LWG 51
|
C++98 |
容器迭代器可能會被 任意函式庫操作使之失效 |
它們僅在 規範要求時才會失效 |
[編輯] 參閱
C++ 具名要求
|
|
數值陣列、陣列遮罩與陣列切片 (類別樣板) [編輯] |
|
|
儲存並操作字元序列 (類別模板) [編輯] |
|
|
唯讀字串檢視 (string view) (類別樣板) [編輯] |