¿Cuál es la forma más sencilla de convertir una matriz en vector?

94

¿Cuál es la forma más sencilla de convertir una matriz en vector?

void test(vector<int> _array)
{
  ...
}

int x[3]={1, 2, 3};
test(x); // Syntax error.

Quiero convertir x de una matriz int a un vector de la manera más sencilla.

Amir Saniyan
fuente

Respuestas:

140

Use el vectorconstructor que toma dos iteradores, tenga en cuenta que los punteros son iteradores válidos y use la conversión implícita de matrices a punteros:

int x[3] = {1, 2, 3};
std::vector<int> v(x, x + sizeof x / sizeof x[0]);
test(v);

o

test(std::vector<int>(x, x + sizeof x / sizeof x[0]));

dónde sizeof x / sizeof x[0]está obviamente 3en este contexto; es la forma genérica de obtener el número de elementos en una matriz. Tenga en cuenta que x + sizeof x / sizeof x[0]apunta un elemento más allá del último elemento.

Fred Foo
fuente
1
¿Puedes explicarlo por favor? Ya leí que vector<int> a(5,10);mean make room for 5 int` y los inicializo con 10. Pero, ¿cómo funciona su x, x + ...? ¿puedes explicar?
Asif Mushtaq
1
@UnKnown en lugar de seleccionar vector<int>::vector(size_type, int), selecciona vector<int>::vector(int*, int*), lo que copia el rango indicado por ese par de punteros. El primero es sobrecarga (2), el segundo es sobrecarga (4) aquí
Caleth
1
En c ++ 11 std :: extension es mejor que el método sizeof. sizeof x / sizeof x[0] == std::extent<decltype(x)>::value
Isaac Pascual
116

Personalmente, me gusta bastante el enfoque de C ++ 2011 porque no requiere que use sizeof()ni recuerde ajustar los límites de la matriz si alguna vez cambia los límites de la matriz (y puede definir la función relevante en C ++ 2003 si lo desea también ):

#include <iterator>
#include <vector>
int x[] = { 1, 2, 3, 4, 5 };
std::vector<int> v(std::begin(x), std::end(x));

Obviamente, con C ++ 2011 es posible que desee usar listas de inicializadores de todos modos:

std::vector<int> v({ 1, 2, 3, 4, 5 });
Dietmar Kühl
fuente
2
¿Copia la matriz o simplemente la señala? me preocupa el rendimiento
kirill_igum
2
std::vector<T>siempre es dueño de los Tobjetos. Esto tiene dos implicaciones: al insertar un objeto en un vector, se copian y se colocan en la memoria. Para objetos razonablemente pequeños, por ejemplo, secuencias de cadenas cortas, la colocación es una ganancia de rendimiento importante. Si sus objetos son grandes y costosos de copiar, es posible que desee almacenar punteros [de alguna manera administrados por recursos] a los objetos. Qué enfoque es más eficiente depende de los objetos, pero usted tiene la opción.
Dietmar Kühl
Entonces, si quiero interconectar bibliotecas c ++ y ac y copiar de c-array a vector y viceversa, ¿no hay forma de pagar la penalización de 2 copias? (estoy usando la biblioteca eigen y gsl)
kirill_igum
16

Los punteros se pueden utilizar como cualquier otro iterador:

int x[3] = {1, 2, 3};
std::vector<int> v(x, x + 3);
test(v)
Rafał Rawicki
fuente
2
En la vida real, es posible que desee abstraer el tamaño de la matriz, por ejemplo, utilizando const size_t X_SIZE = 3;para denotar el tamaño de la matriz o calculándolo a partir de sizeof. Omití esa parte en aras de la legibilidad.
Rafał Rawicki
11

Estás haciendo la pregunta incorrecta aquí: en lugar de forzar todo en un vector, pregunta cómo puedes convertir la prueba para que funcione con iteradores en lugar de un contenedor específico. También puede proporcionar una sobrecarga para mantener la compatibilidad (y manejar otros contenedores al mismo tiempo de forma gratuita):

void test(const std::vector<int>& in) {
  // Iterate over vector and do whatever
}

se convierte en:

template <typename Iterator>
void test(Iterator begin, const Iterator end) {
    // Iterate over range and do whatever
}

template <typename Container>
void test(const Container& in) {
    test(std::begin(in), std::end(in));
}

Lo que te permite hacer:

int x[3]={1, 2, 3};
test(x); // Now correct

( Demostración de Ideone )

Flexo
fuente
"en lugar de forzar todo en un vector, pregunte cómo puede convertir la prueba para que funcione con iteradores en lugar de un contenedor específico". ¿Por qué es esto mejor?
tortuga acuática
1
@aquirdturtle porque ahora, en lugar de solo admitir vectores, admite listas y matrices y aumenta contenedores y transforma iteradores y rangos y ...
Flexo
2
y no necesitas copiar los datos
Lightness Races in Orbit
2

Una forma sencilla puede ser el uso de una assign()función predefinida en la vectorclase.

p.ej

array[5]={1,2,3,4,5};

vector<int> v;
v.assign(array, array+5); // 5 is size of array.
3251_ali
fuente
2
Equivalente al uso del ctor, que se mencionó en las respuestas existentes hace unos siete años. No agrega nada ...
Lightness Races in Orbit