HOWTO · C++

在 C++ STL 中宣告向量陣列

本文介紹如何在 C++ 中宣告向量陣列

本頁內容

本指南說明如何在 C++ 中宣告固定數量的向量,或可調整大小的向量之向量。外層容器決定可新增多少列;每個內層 std::vector 則決定該列可存放多少個值。列數固定時,選擇第一種形式;外層集合需要增加或減少元素時,則選擇第二種形式。

如何選擇固定陣列或向量之向量

向量陣列的列數在編譯時便已固定,但每一列仍是可以獨立增長的向量。向量之向量也能調整列數,而且各列的長度可以不同。因此,向量之向量不一定是矩形矩陣。它適合用來表示鄰接串列等資料,因為每個項目可能有不同數量的相鄰項目。

這兩種形式都以向量作為元素,因此內層向量會自行管理記憶體。無論採用哪種宣告,都不保證每列包含相同數量的值。如果演算法需要矩形形狀,請先將每列初始化為相同寬度,並在修改資料時維持這項條件。

使用 C 樣式陣列語法宣告向量陣列

若列數固定,可以宣告一個元素型別為 std::vector<int> 的陣列,例如 std::vector<int> rows[3];。這個陣列包含三個向量元素。這些向量一開始沒有任何值,但可以使用 rows[0].push_back(10) 將值附加到其中一列。陣列本身無法增長以容納第四個向量;如果列數必須能夠變動,請改用可調整大小的外層容器。

當列數是程式固定結構的一部分時,這種語法很實用。陣列的大小由宣告決定,而每個向量的大小則能在程式執行期間改變。因此,這兩個維度有不同的規則:外層陣列大小固定,內層向量則可以調整大小。

宣告可調整大小的向量之向量

如果列數需要能夠調整,請使用 std::vector<std::vector<int>>。初始化串列可以建立初始長度不同的各列。另一種方式是使用 std::vector<std::vector<int>> rows(3, std::vector<int>(2, 0));,建立三列且每列包含兩個零。在這種建構式形式中,第一個引數是列數;第二個引數是用來初始化每一列的向量副本。

可以使用 rows.push_back({8, 9}) 附加新的一列,或使用 rows[0].push_back(7) 將值加到現有列。增長或縮短其中一列,不會自動調整其他列。若要建立規則的初始網格,請選用建構式形式;若各列長度不同,則可使用初始化串列或逐列建構。

存取並走訪向量之向量

當索引確定有效時,可使用 rows[row][column] 直接存取元素。兩個索引分別套用於不同的向量:第一個選取外層的一列,第二個選取該列中的值。由於各列長度可能不同,適用於某一列的欄索引,未必適用於其他列。

若需要具界限檢查的存取方式,請使用 rows.at(row).at(column);若索引超出範圍,at() 會回報錯誤,而不是默默存取所選向量範圍之外的位置。若要走訪所有值而不假設各列長度相同,請使用巢狀的範圍迴圈。當迴圈需要修改儲存的元素時,請以參考 (int& value) 綁定內層的值;若只讀取資料,則可使用值或常數參考。下方的完整範例示範這兩種宣告形式、索引存取、具界限檢查的存取、附加元素,以及透過參考修改值。

以下完整程式會展示這兩種容器形狀及其值的存取方式:
本節中的程式碼以及顯示的標籤或輸出仍為英文。

#include <iostream>
#include <vector>

int main() {
  std::vector<int> fixed_rows[3] = {{1, 2}, {3}, {4, 5, 6}};
  std::vector<std::vector<int>> rows{{1, 2}, {3}, {4, 5, 6}};

  fixed_rows[0].push_back(7);
  rows.push_back({8, 9});
  rows[1].push_back(7);
  rows.at(0).at(1) = 20;

  std::cout << fixed_rows[0][2] << '\n';
  std::cout << rows.at(0).at(1) << '\n';
  for (auto& row : rows) {
    for (int& value : row) {
      value *= 2;
      std::cout << value << ' ';
    }
    std::cout << '\n';
  }
}