2012-07-05 18 views
31

Zastanawiam się, czy kopiując wektor, kopiuję wektor z jego wartościami (podczas gdy to nie działa z tablicą, a głęboka kopia wymaga pętli lub memcpy).std wektor C++ - głęboka lub płytka kopia

Czy możesz podać wyjaśnienie?

Pozdrowienia

+0

Nie używaj 'memcpy' dla' vector'. Obiekt zawarty w wektorze może nie być POD, mogą to być klasy posiadające funkcje wirtualne. Użyj 'std :: copy' lub simple' vector 'do' wektora 'przydziału. – Ajay

+2

"Głębokie" a "płytkie" rozróżnienie nie ma większego sensu w języku, który domyślnie ceni semantykę i nie próbuje ukrywać faktu, że używa wskaźników (tak, że wskaźniki są obiektami z ich własnymi wartościami, odrębnymi z obiektu, do którego się odnoszą). Kopie zawsze będą wartością podrzędną, a to, czy chodzi o "głębokie" kopiowanie, czy "płytkie" kopiowanie, zależy od twojej definicji. – bames53

Odpowiedz

62

robicie głęboka kopia dowolny czas kopiowania wektora. Ale jeśli wektor jest wektorem wskaźników otrzymujesz kopię wskaźników, a nie wartości są wskazał

Na przykład:

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 Uważam drugi przykład za płytką kopię. 'int * a, * b; a = b; // Płytka kopia'. Czy w przypadku wektorów nie robimy czegoś takiego? BTW, jej de * e * p i nie deap :) – Mahesh

+3

Czasami uważam, że te terminologie są mylące, gdy widzę, że są one używane inaczej, w różnych postach. Można powiedzieć, że w przypadku wskaźników są płytko kopiowane; oba wydają się poprawne, w zależności od tego, jak je interpretujesz. – Nawaz

+5

Zamieszanie prawdopodobnie wynika z braku rozróżnienia między "wskaźnikami" a "punktami". Wskaźniki są po prostu zwykłymi przedmiotami i rzeczywiście są kopiowane dokładnie tak, jak można by oczekiwać. To * pointees *, o których ludzie są zdezorientowani. –

1

Wektor zmieni rozmiar mieć wystarczająco dużo miejsca dla obiektów. Następnie wykona iterację obiektów i wywoła domyślny operator kopiowania dla każdego obiektu.

W ten sposób kopia wektora jest "głęboka". Kopia każdego obiektu w wektorze jest zdefiniowana dla domyślnego operatora kopiowania.

W przykładach ... to jest kod BAD:

#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; 
} 

To jest lepsze Kod:

#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

Lepszy, nadal będzie Reguła Pięciu. :) (Użyłeś starszej reguły trzech) – Arafangion