HOWTO · C++

How to Declare an Array of Vectors in C++ STL

This article introduces how to declare an array of vectors in C++

On this page

This guide shows how to declare either a fixed number of vectors or a resizable vector of vectors in C++. The outer container determines how many rows you can add; each inner std::vector determines how many values that row holds. Choose the first form when the number of rows is fixed, and the second when the outer collection must grow or shrink.

Choose Between a Fixed Array and a Vector of Vectors

An array of vectors has a compile-time fixed number of rows, while each row is still a vector that can grow independently. A vector of vectors can change its row count as well, and each of its rows can have a different length. Therefore, a vector of vectors is not automatically a rectangular matrix. It is useful for data such as adjacency lists, where each item can have a different number of neighbors.

Both forms store vectors as elements, so the inner vectors manage their own memory. Neither declaration guarantees that every row contains the same number of values. If your algorithm requires a rectangular shape, initialize each row to the same width and keep that invariant when modifying the data.

Declare an Array of Vectors with C-Style Array Syntax

For a fixed number of rows, declare an array whose element type is std::vector<int>, such as std::vector<int> rows[3];. The array has three vector elements. Those vectors begin without values, but you can append values to one row with rows[0].push_back(10). The array itself cannot grow to hold a fourth vector; use a resizable outer container if the row count must change.

This syntax is useful when the row count is part of the program’s fixed structure. The array’s size is determined by its declaration, while each vector’s size can change during the program. The two dimensions therefore have different rules: the outer array is fixed, and the inner vectors are resizable.

Declare a Resizable Vector of Vectors

Use std::vector<std::vector<int>> when the number of rows should be resizable. An initializer list can create rows with different initial lengths. Alternatively, std::vector<std::vector<int>> rows(3, std::vector<int>(2, 0)); creates three rows, each containing two zeroes. In this constructor form, the first argument is the row count; the second is a vector copied to initialize each row.

You can append a new row with rows.push_back({8, 9}) or add a value to an existing row with rows[0].push_back(7). Growing or shrinking one row does not automatically resize the others. Select the constructor form for a regular starting grid, and an initializer list or row-by-row construction when row lengths differ.

Access and Iterate Over a Vector of Vectors

Use rows[row][column] for direct access when the indices are known to be valid. Each subscript is applied to a different vector: the first selects an outer row, and the second selects a value within that row. Since rows can differ in length, a column index that works for one row may not work for another.

Use rows.at(row).at(column) when you want bounds-checked access; at() reports an out-of-range access instead of silently indexing past the selected vector. To visit all values without assuming equal row lengths, use nested range-based loops. Bind the inner value by reference (int& value) when the loop should modify stored elements; use a value or a const reference for read-only work. The complete example below demonstrates both declaration forms, indexing, checked access, appending, and modifying values by reference.

This complete program shows both container shapes and accesses their values:

#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';
  }
}