HOWTO · C++

Declarar un array de vectores en C++ STL

Este artículo presenta cómo declarar un array de vectores en C++

En esta página

Esta guía muestra cómo declarar una cantidad fija de vectores o un vector de vectores redimensionable en C++. El contenedor externo determina cuántas filas se pueden añadir; cada std::vector interno determina cuántos valores contiene esa fila. Elija la primera forma cuando la cantidad de filas sea fija y la segunda cuando la colección externa deba poder crecer o reducirse.

Elegir entre un array fijo y un vector de vectores

Un array de vectores tiene una cantidad de filas fija en tiempo de compilación, aunque cada fila sigue siendo un vector que puede crecer de forma independiente. Un vector de vectores también puede cambiar la cantidad de filas, y cada una puede tener una longitud distinta. Por lo tanto, un vector de vectores no es automáticamente una matriz rectangular. Resulta útil para datos como las listas de adyacencia, donde cada elemento puede tener una cantidad diferente de vecinos.

Ambas formas almacenan vectores como elementos, por lo que los vectores internos administran su propia memoria. Ninguna declaración garantiza que todas las filas contengan la misma cantidad de valores. Si el algoritmo requiere una estructura rectangular, inicialice todas las filas con la misma anchura y mantenga esa condición al modificar los datos.

Declarar un array de vectores con sintaxis de estilo C

Para tener una cantidad fija de filas, declare un array cuyo tipo de elemento sea std::vector<int>, por ejemplo, std::vector<int> rows[3];. El array contiene tres elementos vector. Estos vectores empiezan vacíos, pero puede añadir valores a una fila con rows[0].push_back(10). El array no puede crecer para contener un cuarto vector; si la cantidad de filas debe cambiar, use un contenedor externo redimensionable.

Esta sintaxis resulta útil cuando la cantidad de filas forma parte de la estructura fija del programa. El tamaño del array queda determinado por su declaración, mientras que el tamaño de cada vector puede cambiar durante la ejecución. Por tanto, las dos dimensiones siguen reglas distintas: el array externo es fijo y los vectores internos son redimensionables.

Declarar un vector de vectores redimensionable

Use std::vector<std::vector<int>> cuando la cantidad de filas deba poder cambiar. Una lista de inicialización puede crear filas con distintas longitudes iniciales. Otra opción es std::vector<std::vector<int>> rows(3, std::vector<int>(2, 0));, que crea tres filas con dos ceros cada una. En esta forma del constructor, el primer argumento indica la cantidad de filas y el segundo es un vector que se copia para inicializar cada fila.

Puede añadir una fila nueva con rows.push_back({8, 9}) o agregar un valor a una fila existente con rows[0].push_back(7). Alargar o acortar una fila no redimensiona las demás automáticamente. Elija la forma del constructor para una cuadrícula inicial regular, y una lista de inicialización o la construcción fila por fila cuando las longitudes sean distintas.

Acceder a un vector de vectores e iterarlo

Use rows[row][column] para acceder directamente cuando sepa que los índices son válidos. Cada índice se aplica a un vector distinto: el primero selecciona una fila externa y el segundo, un valor dentro de esa fila. Como las filas pueden tener longitudes distintas, un índice de columna válido para una fila quizá no lo sea para otra.

Use rows.at(row).at(column) si necesita que se comprueben los límites; at() informa de un acceso fuera de rango en vez de indexar silenciosamente más allá del vector seleccionado. Para recorrer todos los valores sin presuponer que las filas tienen la misma longitud, use bucles anidados basados en rangos. Vincule el valor interno por referencia (int& value) si el bucle debe modificar los elementos almacenados; para una lectura, use una copia o una referencia constante. El ejemplo completo de abajo muestra ambas formas de declaración, el acceso por índices, el acceso con comprobación de límites, cómo añadir elementos y cómo modificarlos mediante referencias.

Este programa completo muestra ambas estructuras de contenedor y accede a sus valores:

El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.

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