2012-07-05 43 views
31

Me pregunto si al copiar un vector estoy copiando el vector con sus valores (mientras que esto no está funcionando con matriz, y la copia profunda necesita un bucle o memcpy).std vector C++ - copia profunda o superficial

¿Podría darnos una explicación?

Saludos

+0

No utilice '' memcpy' para vECTOR'. El objeto contenido en el vector puede no ser POD, pueden ser clases que tienen funciones virtuales. Utilice 'std :: copy' o simple' vector 'en la asignación' vector '. – Ajay

+2

La distinción "profundo" frente a "superficial" no tiene mucho sentido en un lenguaje que predetermina su valor semántico y no intenta ocultar el hecho de que utiliza punteros (de modo que los punteros son objetos con sus propios valores, distintos del objeto al que hacen referencia). Las copias siempre serán por valor, y si eso constituye una copia 'profunda' contra una copia 'superficial' depende de su definición. – bames53

Respuesta

62

Usted está haciendo una copia en profundidad cualquier momento se copia un vector. Pero si su vector es un vector de punteros que está recibiendo la copia de los punteros, no los valores están apuntado a

Por ejemplo:

std::vector<Foo> f; 
std::vector<Foo> cp = f; //deep copy. All Foo copied 

std::vector<Foo*> f; 
std::vector<Foo*> cp = f; //deep copy (of pointers), or shallow copy (of objects). 
//All pointers to Foo are copied, but not Foo themselves 
+2

+1 Consideraría el segundo ejemplo como una copia superficial. 'int * a, * b; a = b; // Shallow copy'. En el caso de los vectores también, ¿no estamos haciendo algo como esto? Por cierto, es de * e * p y no deap :) – Mahesh

+3

A veces encuentro estas terminologías confusas cuando veo que se usan de manera diferente, en diferentes publicaciones. Uno podría decir, en el caso de los punteros, que son poco profundos; ambos parecen ser correctos, dependiendo de cómo los interpretes. – Nawaz

+5

La confusión probablemente proviene de una distinción que falta entre "punteros" y "punteros". Los punteros son solo objetos ordinarios, y de hecho se copian exactamente de la manera que cabría esperar. Son los * puntos * con los que las personas están confundidas. –

1

vector cambiará de tamaño para tener suficiente espacio para los objetos. Luego recorrerá los objetos y llamará al operador de copia predeterminado para cada objeto.

De esta manera, la copia del vector es 'profunda'. La copia de cada objeto en el vector es lo que se define para el operador de copia predeterminado.

En los ejemplos ... este es el código malo:

#include <iostream> 
#include <vector> 

using namespace std; 

class my_array{ 
public: 
    int *array; 
    int size; 
    my_array(int size, int init_val):size(size){ 
     array = new int[size]; 
     for(int i=0; i<size; ++i) 
      array[i]=init_val; 
    } 
    ~my_array(){ 
     cout<<"Destructed "<<array[0]<<endl; 
     if(array != NULL) 
      delete []array; 
     array = NULL; 
     size = 0; 
    } 

}; 

void add_to(vector<my_array> &container){ 
    container.push_back(my_array(4,1)); 
} 

int main(){ 

    vector<my_array> c; 
    { 
     my_array a(5,0); 
     c.push_back(a); 
    } 
    add_to(c); 
    //At this point the destructor of c[0] and c[1] has been called. 
    //However vector still holds their 'remains' 
    cout<<c[0].size<<endl; //should be fine, as it copies over with the = operator 
    cout<<c[0].array[0]<<endl;//undefined behavior, the pointer will get copied, but the data is not valid 
    return 0; 
} 

Esto es mejor código:

#include <iostream> 
#include <vector> 

using namespace std; 

class my_array{ 
public: 
    int *array; 
    int size; 
    my_array(int size, int init_val):size(size){ 
     cout<<"contsructed "<<init_val<<endl; 
     array = new int[size]; 
     for(int i=0; i<size; ++i) 
      array[i]=init_val; 
    } 
    my_array(const my_array &to_copy){ 
     cout<<"deep copied "<<to_copy.array[0]<<endl; 
     array = new int[to_copy.size]; 
     size = to_copy.size; 
     for(int i=0; i<to_copy.size; i++) 
      array[i]=to_copy.array[i]; 
    } 

    ~my_array(){ 
     cout<<"Destructed "<<array[0]<<endl; 
     if(array != NULL) 
      delete []array; 
     array = NULL; 
     size = 0; 
    } 

}; 

void add_to(vector<my_array> &container){ 
    container.push_back(my_array(4,1)); 
} 

int main(){ 

    vector<my_array> c; 
    { 
     my_array a(5,0); 
     c.push_back(a); 
    } 
    add_to(c); 
    //At this point the destructor of c[0] and c[1] has been called. 
    //However vector holds a deep copy' 
    cout<<c[0].size<<endl; //This is FINE 
    cout<<c[0].array[0]<<endl;//This is FINE 
    return 0; 
} 
+0

Mejor, aún, sería la Regla del Cinco. :) (Usaste la antigua regla de tres) – Arafangion

Cuestiones relacionadas