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?


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);

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.


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.


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


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.


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

-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());

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.