HOWTO · C++
Cómo crear un vector de vectores en C++
Aprende a crear un vector de vectores en C++, llenarlo con valores de muestra y modificar sus elementos.
En esta página
Un vector de vectores almacena filas como objetos std::vector dentro de un std::vector externo. Para crear uno con un número conocido de filas y columnas, construye el vector externo indicando la cantidad de filas y usa como valor inicial un vector interno con la cantidad de columnas. Los ejemplos muestran cómo crear una cuadrícula con dimensiones definidas, llenarla con valores de muestra y modificar sus elementos. Este patrón resulta útil cuando cada fila debe ser un vector y el programa determina cuántas filas o columnas necesita.
Crear un vector de vectores en C++ con el constructor de tamaño y valor
El constructor de tamaño y valor deja explícitas las dimensiones y el contenido inicial. Por ejemplo, std::vector<std::vector<int>> grid(rows, std::vector<int>(columns, 0)); crea rows vectores internos, cada uno con columns enteros inicializados en cero. El vector interno se construye como valor con el que se inicializan las filas del vector externo. Esta construcción especifica un tamaño y un valor inicial; no es una construcción por defecto. Para consultar la forma independiente con constructor por defecto, véase la referencia sobre el constructor por defecto.
Este ejemplo crea cuatro filas con seis enteros cada una. Los índices de un vector empiezan en cero: [2][2] selecciona la tercera fila y la tercera columna. Las llamadas anidadas a .at() seleccionan la cuarta fila y la cuarta columna. .at() comprueba cada índice frente al tamaño del vector correspondiente y señala un acceso fuera de rango si el índice no corresponde a un elemento; el acceso con corchetes es más conciso cuando se sabe que los índices son válidos.
#include <iostream>
#include <vector>
int main() {
constexpr int LENGTH = 4;
constexpr int WIDTH = 6;
std::vector<std::vector<int>> grid(LENGTH, std::vector<int>(WIDTH, 0));
grid[2][2] = 12;
std::cout << grid[2][2] << '\n';
grid.at(3).at(3) = 99;
std::cout << grid[3][3] << '\n';
return 0;
}
12
99
La salida queda determinada por las dos asignaciones. Usa índices válidos para las dimensiones de filas y columnas: el vector externo selecciona una fila y el vector interno de esa fila selecciona una columna. Si las dimensiones no son fijas, el programa puede obtener de sus datos tanto la cantidad de filas como el tamaño de cada una.
Usar la función rand para llenar un vector de vectores con valores de muestra en C++
Una vez creada la cuadrícula, unos bucles anidados pueden recorrer cada entero y asignarle un valor de muestra. El programa siguiente inicializa rand con la hora actual y usa % 100 para producir valores del 0 al 99. Los valores impresos varían entre ejecuciones, por lo que no existe una única salida que se pueda copiar. El ejemplo incluye <cstdlib> para rand y srand, y <ctime> para std::time.
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <vector>
int main() {
constexpr int LENGTH = 4;
constexpr int WIDTH = 6;
std::vector<std::vector<int>> grid(LENGTH, std::vector<int>(WIDTH, 0));
std::srand(static_cast<unsigned int>(std::time(nullptr)));
for (auto& row : grid) {
for (int& value : row) {
value = std::rand() % 100;
std::cout << value << ' ';
}
std::cout << '\n';
}
return 0;
}
Estos datos de muestra sirven para demostraciones y tareas pequeñas no sensibles. rand no es adecuado para uso criptográfico. Además, la operación de resto puede sesgar los resultados si la cantidad de valores posibles del generador no es divisible por 100. Para simulaciones o código de aplicación que necesite una distribución más sólida, elige una herramienta de generación de números aleatorios que satisfaga ese requisito; no tomes este ejemplo breve como un generador de uso general.
Usar bucles anidados basados en rangos para modificar cada elemento de un vector de vectores en C++
Un bucle basado en rangos recorre cada fila y otro bucle anidado recorre los enteros de esa fila. En int& value, & hace que value sea una referencia al elemento almacenado, de modo que una asignación modifica el vector. Sin esa referencia, la variable del bucle sería una copia y actualizarla no cambiaría el entero almacenado. Este programa imprime la cuadrícula antes y después de multiplicar cada elemento por tres.
#include <iostream>
#include <vector>
void print(const std::vector<std::vector<int>>& grid) {
for (const auto& row : grid) {
for (int value : row) {
std::cout << value << ' ';
}
std::cout << '\n';
}
}
int main() {
std::vector<std::vector<int>> grid{{1, 2, 3}, {4, 5, 6}};
std::cout << "Before:\n";
print(grid);
for (auto& row : grid) {
for (int& value : row) {
value *= 3;
}
}
std::cout << "After:\n";
print(grid);
return 0;
}
Cada vector interno administra su propia secuencia de enteros y el vector externo almacena los vectores que representan las filas. Los enteros de una misma fila son contiguos, pero la estructura anidada completa no forma un único bloque bidimensional contiguo. Esta descripción se limita a la disposición en memoria y no establece una comparación general de velocidad: el rendimiento depende de la operación y de la carga de trabajo. Un vector anidado resulta útil cuando las filas son unidades independientes o se necesitan las operaciones habituales de std::vector. Si una tarea requiere específicamente un único bloque contiguo, elige una representación diseñada para esa disposición.