HOWTO · C++

Cómo convertir un vector en una array en C++

Este artículo introduce cómo convertir un vector en un array en C++

En esta página

Un std::vector almacena sus elementos de forma contigua, por lo que las API que aceptan un puntero y un número de elementos pueden usar directamente ese almacenamiento. Esto permite acceder a los elementos como si fueran los de un array, pero no crea un array independiente: el puntero apunta a elementos que pertenecen al vector. Si el código receptor necesita almacenamiento independiente, copia los elementos en un destino con espacio suficiente.

Usa data() para obtener una vista temporal mediante un puntero, std::copy para crear una copia independiente y std::transform cuando también debas modificar los valores copiados. Mantén vivo el vector mientras uses un puntero a sus elementos. Las operaciones que reasignan el almacenamiento del vector invalidan los punteros que apuntan a él.

Usa data() para acceder a los elementos de un vector como si fueran los de un array

El miembro data() devuelve un puntero al almacenamiento contiguo de los elementos del vector. Combínalo con size() al pasar los datos a una API que acepte un puntero y un recuento. El puntero es un alias del vector: escribir a través de él modifica el elemento correspondiente y no debe seguir usándose después de que el vector deje de existir o de que una operación reasigne su almacenamiento.

Ejecuta este ejemplo:

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

#include <cstddef>
#include <iostream>
#include <vector>

int main() {
  std::vector<int> values{1, 2, 3};
  int* elements = values.data();
  elements[1] = 20;

  for (std::size_t i = 0; i < values.size(); ++i) {
    if (i != 0) std::cout << ' ';
    std::cout << elements[i];
  }
  std::cout << '\n';
}
1 20 3

Aunque se puede obtener data() para un vector que podría estar vacío, no desreferencies el puntero devuelto si no hay ningún elemento. Al recorrer los elementos mediante el puntero, usa siempre el tamaño del vector como límite.

Usa el operador de dirección con un vector no vacío

Si sabes que el vector contiene al menos un elemento, &values[0] apunta al primero y permite recorrer los elementos del vector mediante índices. El puntero tiene la misma propiedad y vida útil que uno obtenido con data(). La condición previa es importante: acceder al elemento cero de un vector vacío no es válido. Si el vector podría estar vacío, prefiere data(); aun así, comprueba el tamaño antes de desreferenciar el puntero o de pasarlo a código que requiera al menos un elemento.

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

#include <cstddef>
#include <iostream>
#include <vector>

int main() {
  std::vector<int> values{4, 5, 6};
  int* elements = &values[0];

  for (std::size_t i = 0; i < values.size(); ++i) {
    if (i != 0) std::cout << ' ';
    std::cout << elements[i];
  }
  std::cout << '\n';
}
4 5 6

Copia los elementos del vector en un array con std::copy()

std::copy escribe cada elemento de origen en un rango de destino ya creado; no reserva ese rango. Si el número de elementos se conoce en tiempo de compilación, std::array proporciona un objeto array real de tamaño fijo. Su tamaño y tipo de elemento deben permitir almacenar los datos de origen. Si el recuento solo se conoce durante la ejecución, usa almacenamiento dinámico adecuado, como un std::vector de destino o un array dinámico propio si la API receptora lo requiere específicamente.

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

#include <algorithm>
#include <array>
#include <cstddef>
#include <iostream>
#include <vector>

int main() {
  std::vector<int> values{7, 8, 9};
  std::array<int, 3> result{};
  std::copy(values.begin(), values.end(), result.begin());

  for (std::size_t i = 0; i < result.size(); ++i) {
    if (i != 0) std::cout << ' ';
    std::cout << result[i];
  }
  std::cout << '\n';
}
7 8 9

El destino es independiente del origen, así que modificar result no modifica values. Antes de llamar a std::copy, comprueba que el destino tenga espacio para todos los elementos de origen; el algoritmo no verifica su capacidad. Un array integrado de longitud variable no forma parte del C++ estándar, porque su tamaño debe ser una constante conocida en tiempo de compilación.

Transforma los elementos del vector al copiarlos con std::transform()

Usa std::transform cuando la copia también deba calcular valores nuevos. Su rango de salida debe tener espacio para un resultado por cada elemento de entrada, igual que con std::copy. Este ejemplo duplica cada entero y lo almacena en un std::array independiente.

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

#include <algorithm>
#include <array>
#include <cstddef>
#include <iostream>
#include <vector>

int main() {
  std::vector<int> values{2, 3, 4};
  std::array<int, 3> doubled{};
  std::transform(values.begin(), values.end(), doubled.begin(),
                 [](int value) { return value * 2; });

  for (std::size_t i = 0; i < doubled.size(); ++i) {
    if (i != 0) std::cout << ' ';
    std::cout << doubled[i];
  }
  std::cout << '\n';
}
4 6 8

Si quieres una copia sin cambios, std::copy expresa la intención de forma más directa. Elige un tipo de destino que pueda almacenar los resultados transformados y dale espacio para todo el rango de entrada.

Copia los elementos del vector con un bucle for

Un bucle permite controlar explícitamente cada asignación. También aquí se debe dimensionar correctamente el destino: cada índice usado para acceder al origen debe ser válido en el destino. Si el destino tiene tamaño fijo en tiempo de compilación, comprueba que su extensión coincida con la del vector antes de copiar. Para una entrada cuyo tamaño se conoce durante la ejecución, usa un destino dinámico con espacio suficiente.

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

#include <array>
#include <cstddef>
#include <iostream>
#include <vector>

int main() {
  std::vector<int> values{10, 11, 12};
  std::array<int, 3> result{};

  for (std::size_t i = 0; i < values.size(); ++i) {
    result[i] = values[i];
  }

  for (std::size_t i = 0; i < result.size(); ++i) {
    if (i != 0) std::cout << ' ';
    std::cout << result[i];
  }
  std::cout << '\n';
}
10 11 12

Elige data() cuando una API necesite una vista temporal de los elementos que pertenecen al vector, y mantén el vector vivo y estable mientras se use. Usa std::copy si necesitas almacenamiento separado, std::transform si debes modificar los valores durante la copia y un bucle cuando resulte útil controlar cada elemento. Un std::array de tamaño fijo es adecuado cuando el número de elementos se conoce en tiempo de compilación; en caso contrario, usa un destino de tamaño dinámico si la API lo permite.