HOWTO · C++
Como Converter Vetor em Array em C++
Este artigo introduz como converter um vetor em um array em C++
Nesta página
Um std::vector armazena seus elementos de forma contígua, portanto APIs que aceitam um ponteiro e a quantidade de elementos podem usar esse armazenamento diretamente. Isso permite acesso no estilo de um array, mas não cria um array separado: o ponteiro aponta para elementos pertencentes ao vetor. Se o código que recebe os dados precisar de armazenamento independente, copie os elementos para um destino com espaço suficiente.
Use data() para obter uma visualização temporária por ponteiro, std::copy para criar uma cópia independente e std::transform quando os valores copiados precisarem ser alterados. Mantenha o vetor vivo enquanto um ponteiro para seus elementos estiver em uso. Operações que realocam o vetor invalidam os ponteiros para seu armazenamento.
Use data() para acessar os elementos de um vetor como um array
O membro data() retorna um ponteiro para o armazenamento contíguo dos elementos do vetor. Combine-o com size() ao passar os dados para uma API que aceite um ponteiro e a quantidade de elementos. O ponteiro referencia o próprio vetor: escrever por meio dele altera o elemento correspondente, e ele não pode continuar em uso depois que o vetor deixa de existir ou uma operação realoca seu armazenamento.
Execute este exemplo:
O código e os rótulos ou saídas exibidos nesta seção permanecem em 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
Para um vetor que pode estar vazio, é possível obter data(), mas não desreferencie o ponteiro retornado a menos que exista um elemento. Ao indexar por meio do ponteiro, use sempre o tamanho do vetor como limite.
Use o operador de endereço com um vetor não vazio
Se houver certeza de que o vetor contém pelo menos um elemento, &values[0] aponta para o primeiro elemento e pode ser usado para acessar os elementos do vetor por índice. Esse ponteiro tem a mesma propriedade e o mesmo tempo de vida que um ponteiro obtido com data(). Essa condição é importante: acessar o elemento zero quando o vetor está vazio é inválido. Prefira data() quando o vetor puder estar vazio e, ainda assim, verifique o tamanho antes de desreferenciar o ponteiro ou passá-lo a um código que exija pelo menos um elemento.
O código e os rótulos ou saídas exibidos nesta seção permanecem em 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
Copie os elementos do vetor para um array com std::copy()
std::copy grava cada elemento de origem em um intervalo de destino já criado; o algoritmo não aloca esse intervalo. Quando a quantidade de elementos é conhecida em tempo de compilação, std::array fornece um objeto de array real com tamanho fixo. O tamanho e o tipo dos elementos precisam comportar os dados de origem. Se a quantidade só for conhecida em tempo de execução, use armazenamento dinâmico adequado, como um destino std::vector ou um array dinâmico com propriedade própria, caso a API receptora exija especificamente um.
O código e os rótulos ou saídas exibidos nesta seção permanecem em 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
O destino é independente da origem, portanto alterar result não altera values. Antes de chamar std::copy, verifique se o destino comporta todos os elementos de origem; o algoritmo não verifica a capacidade do destino. Um array nativo de tamanho variável não faz parte do C++ padrão, pois seu limite deve ser uma constante conhecida em tempo de compilação.
Transforme os elementos do vetor durante a cópia com std::transform()
Use std::transform quando a cópia também precisar calcular novos valores. Assim como em std::copy, o intervalo de saída precisa comportar um resultado para cada elemento de entrada. Este exemplo dobra cada inteiro ao armazená-lo em um std::array independente.
O código e os rótulos ou saídas exibidos nesta seção permanecem em 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
Para uma cópia sem alterações, std::copy expressa a intenção de forma mais direta. Escolha um tipo de destino capaz de armazenar os resultados transformados e dimensione-o para todo o intervalo de entrada.
Copie os elementos do vetor com um loop for
Um loop permite controlar explicitamente cada atribuição. A mesma exigência de tamanho do destino se aplica: todo índice usado na origem precisa ser válido no destino. Se o destino tiver tamanho definido em tempo de compilação, confira se sua extensão corresponde ao vetor antes de copiar; para entradas cujo tamanho só é conhecido em tempo de execução, use um destino dinâmico dimensionado adequadamente.
O código e os rótulos ou saídas exibidos nesta seção permanecem em 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
Escolha data() quando uma API precisar de uma visualização temporária dos elementos pertencentes ao vetor e mantenha o vetor vivo e sem realocações durante esse uso. Use std::copy quando precisar de armazenamento separado, std::transform quando os valores precisarem mudar durante a cópia e um loop quando for útil controlar cada elemento. Um std::array de tamanho fixo é adequado quando a quantidade é conhecida em tempo de compilação; caso contrário, use um destino com tamanho ajustável em tempo de execução, se a API permitir.