C++容器(STL容器)

2020-07-16 10:04:25
容器(container)用於存放資料的類別範本。可變長陣列、連結串列、平衡二元樹等資料結構在 STL 中都被實現為容器。

程式設計師使用容器時,即將容器類別範本範例化為容器類時,會指明容器中存放的元素是什麼型別的。

容器中可以存放基本型別的變數,也可以存放物件。物件或基本型別的變數被插入容器中時,實際插入的是物件或變數的一個複製品。

STL 中的許多演算法(即函數模板),如排序、查詢等演算法,在執行過程中會對容器中的元素進行比較。這些演算法在比較元素是否相等時通常用運算子進行,比較大小通常用<運算子進行,因此,被放入容器的物件所屬的類最好過載==<運算子,以使得兩個物件用==<進行比較是有定義的。

容器分為兩大類。

順序容器

順序容器有以下三種:可變長動態陣列 vector、雙端佇列 deque、雙向連結串列 list。

它們之所以被稱為順序容器,是因為元素在容器中的位置同元素的值無關,即容器不是排序的。將元素插入容器時,指定在什麼位置(尾部、頭部或中間某處)插入,元素就會位於什麼位置。

關聯容器

關聯容器有以下四種:set、multiset、map、multimap。關聯容器內的元素是排序的。插入元素時,容器會按一定的排序規則將元素放到適當的位置上,因此插入元素時不能指定位置。

預設情況下,關聯容器中的元素是從小到大排序(或按關鍵字從小到大排序)的,而且用<運算子比較元素或關鍵字大小。因為是排好序的,所以關聯容器在查詢時具有非常好的效能。

除了以上兩類容器外,STL 還在兩類容器的基礎上遮蔽一部分功能,突出或增加另一部分功能,實現了三種容器介面卡:棧 stack、佇列 queue、優先順序佇列 priority_queue。

為稱呼方便起見,本教學後面將容器和容器介面卡統稱為容器。

容器都是類別範本。它們範例化後就成為容器類。用容器類定義的物件稱為容器物件。

例如,vector<int>是一個容器類的名字,vector<int> a;就定義了一個容器物件 a,a 代表一個長度可變的陣列,陣列中的每個元素都是 int 型別的變數;vector<double> b;定義了另一個容器物件 b,a 和 b 的型別是不同的。本教學後文所說的“容器”,有時也指“容器物件”,讀者需要根據上下文自行判別。

任何兩個容器物件,只要它們的型別相同,就可以用 <、<=、>、>=、==、!= 進行詞典式的比較運算。假設 a、b 是兩個型別相同的容器物件,這些運算子的運算規則如下。
  • a == b:若 a 和 b 中的元素個數相同,且對應元素均相等,則a == b的值為 true,否則值為 false。元素是否相等是用==運算子進行判斷的。
  • a<b:規則類似於詞典中兩個單詞比較大小,從頭到尾依次比較每個元素,如果發生 a 中的元素小於 b 中的元素的情況,則a<b的值為 true;如果沒有發生 b 中的元素小於 a 中的元素的情況,且 a 中的元素個數比 b 少,a<b的值也為 true;其他情況下值為 false。元素比較大小是通過<運算子進行的。
  • a != b:等價於 !(a == b)。
  • a > b:等價於 b < a。
  • a <= b:等價於 !(b < a)。
  • a >= b:等價於 !(a < b)。

所有容器都有以下兩個成員函數:
  • int size():返回容器物件中元素的個數。
  • bool empty():判斷容器物件是否為空。

順序容器和關聯容器還有以下成員函數:
  • begin():返回指向容器中第一個元素的疊代器。
  • end():返回指向容器中最後一個元素後面的位置的疊代器。
  • rbegin():返回指向容器中最後一個元素的反向疊代器。
  • rend():返回指向容器中第一個元素前面的位置的反向疊代器。
  • erase(...):從容器中刪除一個或幾個元素。該函數引數較複雜,此處省略。
  • clear():從容器中刪除所有元素。

如果一個容器是空的,則 begin() 和 end() 的返回值相等,rbegin() 和 rend() 的返回值也相等。

順序容器還有以下常用成員函數:
  • front():返回容器中第一個元素的參照。
  • back():返回容器中最後一個元素的參照。
  • push_back():在容器末尾增加新元素。
  • pop_back():刪除容器末尾的元素。
  • insert(...):插入一個或多個元素。該函數引數較複雜,此處省略。