forma rápida de copiar un vector en otro

155

Prefiero dos formas:

void copyVecFast(const vec<int>& original)
{
  vector<int> newVec;
  newVec.reserve(original.size());
  copy(original.begin(),original.end(),back_inserter(newVec));
}

void copyVecFast(vec<int>& original)
{

  vector<int> newVec;
  newVec.swap(original); 
}

¿Cómo lo haces?

gsamaras
fuente
14
El segundo tiene un nombre engañoso, ya que no es una copia (aunque es rápido).
Anónimo

Respuestas:

125

Su segundo ejemplo no funciona si envía el argumento por referencia. Querías decir

void copyVecFast(vec<int> original) // no reference
{

  vector<int> new_;
  new_.swap(original); 
}

Eso funcionaría, pero una forma más fácil es

vector<int> new_(original);
rlbond
fuente
Bien, funciona Pero no funciona para una matriz de vectores: por ejemplo: vector <int> A [n];
ABcDexter
8
Eso es cambiar, no copiar.
sdd
1
@sdd: no, no lo es. Revisa la lista de argumentos. originales una copia del argumento de la función.
rlbond
@rlbond Votó accidentalmente la respuesta :(, ¿Puedes editar la publicación, para que pueda eliminar el voto negativo y dar el voto positivo?
Shubham Sharma hace
250

Sin embargo, no son lo mismo, ¿verdad? Uno es una copia, el otro es un intercambio . De ahí los nombres de las funciones.

Mi favorito es:

a = b;

Donde ay bson vectores.

Daniel Earwicker
fuente
3
De hecho, el enfoque pasa por valor, el compilador llama al constructor de la copia y luego intercambia ese elemento recién creado. Es por eso que rlbond sugiere llamar al constructor de copias directamente para lograr el mismo efecto.
David Rodríguez - dribeas
1
Sin embargo, no puede llamar a rlbon sin una función que pase el original como val. De lo contrario, el original será vacío. La segunda solución se aseguró de que siempre llamará por valor y, por lo tanto, no perderá la fecha en el vector original. (Asumiendo acuerdos de intercambio con punteros)
Eyad Ebrahim
¿Eso no moverá los elementos de b a a (dejando b con tamaño == 0)?
Jonathan.
1
@ Jonathan. Asumiendo que estás hablando, a = bentonces no. Asignación significa: aigualar bsin cambiar b. Por el contrario, std::swap(a, b)sería intercambiar sus contenidos (por lo que b's sizeahora sería lo a' s había sido antes). Quizás esté pensando en una operación de movimiento (como ocurre en C ++ 11, pero no en una tarea ordinaria como esta). Tal movimiento dejaría ben un, ejem, estado "interesante" - ver stackoverflow.com/questions/17730689/…
Daniel Earwicker
1
@ Jonathan. Tenga en cuenta el doble ampersand &&. Esa versión solo se utilizará para una referencia de valor. No coincidirá con ningún valor no constante (como ben mi ejemplo anterior). Puede convertirse ben uno diciendo a = std::move(b);Ver en.cppreference.com/w/cpp/language/value_category para niveles de complejidad aún mayores.
Daniel Earwicker
74

Esta es otra forma válida de hacer una copia de un vector, solo use su constructor:

std::vector<int> newvector(oldvector);

Esto es aún más simple que usar std::copypara recorrer todo el vector de principio a fin hasta std::back_insertel nuevo vector.

Dicho esto, el tuyo .swap()no es una copia, sino que intercambia los dos vectores. ¡Modificaría el original para no contener nada más! Que no es una copia.

X-Istence
fuente
Más flexible para mí es a = b;porque ya tengo un campo de miembros ay solo necesito asignarlo con el nuevo valor deb
truthadjustr hace
20

Respuesta directa:

  • Use un =operador

Podemos usar la función miembro público std::vector::operator=del contenedor std::vectorpara asignar valores de un vector a otro.

  • Use una función constructora

Además, una función constructora también tiene sentido. Una función constructora con otro vector como parámetro (p x. Ej. ) Construye un contenedor con una copia de cada uno de los elementos x, en el mismo orden.

Precaución:

  • No utilice std::vector::swap

std::vector::swapno está copiando un vector a otro, en realidad está intercambiando elementos de dos vectores, tal como sugiere su nombre. En otras palabras, el vector de origen para copiar se modifica después de que std::vector::swapse llama, lo que probablemente no sea lo que se espera.

  • Copia profunda o superficial?

Si los elementos en el vector fuente son punteros a otros datos, a veces se necesita una copia profunda.

De acuerdo con wikipedia:

Una copia profunda, lo que significa que los campos están desreferenciados: en lugar de referencias a objetos que se copian, se crean nuevos objetos de copia para cualquier objeto referenciado, y las referencias a estos se colocan en B.

En realidad, actualmente no hay una forma integrada en C ++ para hacer una copia profunda. Todas las formas mencionadas anteriormente son poco profundas. Si es necesaria una copia profunda, puede atravesar un vector y hacer una copia de las referencias manualmente. Alternativamente, se puede considerar un iterador para atravesar. La discusión sobre el iterador está más allá de esta pregunta.

Referencias

La página de std::vectoren cplusplus.com

Jerry Yang
fuente
14

no debe usar el intercambio para copiar vectores, cambiaría el vector "original".

pasar el original como parámetro al nuevo en su lugar.

Raz
fuente
14
new_vector.assign(old_vector.begin(),old_vector.end()); // Method 1
new_vector = old_vector; // Method 2
FaridLU
fuente
-14

En caso de que el vector YA existiera y quisieras copiarlo, puedes hacer esto:

newVec.resize(oldVec.size());
memcpy(&newVec.at(0), &oldVec.at(0), oldVec.size());
sgowd
fuente
1
Por favor no recuerdes. Además, esto no funcionará ya que memcpy toma el tamaño en bytes. Además, si el otro vector ya existe, puede hacer newVec = oldVeclo mismo que una de las otras respuestas.
FDinoff
Sí, tiene usted razón. Yo no vi eso. @FDinoff, aunque debajo de uno funciona, ¿por qué sugiere no usar memcpy? Parece ser mucho más rápido que newVec = oldVec. memcpy (& newVec.at (0), & oldVec.at (0), oldVec.size () * sizeof (int));
sgowd
1
En el caso general, copiar un objeto sin llamar a su constructor de copias podría generar errores sutiles. En este caso, habría pensado que habrían tenido el mismo rendimiento. Si no fuera así, diría que el vector no estaba optimizado para el rendimiento, ya que ya debería estar haciendo esto. ¿Realmente escribiste un punto de referencia?
FDinoff
No te estaba criticando. El líder de mi equipo también sugirió lo mismo y estaba tratando de entender.
sgowd
(No pensé que me estuvieras criticando). ¿Todavía hay algo que no entiendes?
FDinoff