2012-07-05 35 views
31

Tôi tự hỏi liệu sao chép một vector tôi sao chép véc tơ với các giá trị của nó (trong khi điều này không làm việc với mảng, và bản sao sâu cần một vòng lặp hoặc memcpy).std vector C++ - bản sao sâu hoặc nông

Bạn có thể gợi ý giải thích không?

Kính trọng

+0

Đừng sử dụng 'memcpy' cho' vector'. Đối tượng chứa trong vector có thể không phải là POD, chúng có thể là các lớp có chức năng ảo. Sử dụng 'std :: copy' hoặc đơn giản' vector 'to' vector 'gán. – Ajay

+2

Sự khác biệt 'sâu' so với 'nông' không có ý nghĩa nhiều trong ngôn ngữ mặc định để đánh giá ngữ nghĩa và không cố che giấu thực tế rằng nó sử dụng con trỏ (để con trỏ là đối tượng có giá trị riêng của chúng, riêng biệt từ đối tượng mà họ tham chiếu). Bản sao sẽ luôn là giá trị theo giá trị, và liệu bản sao đó có tạo thành bản sao chép 'sâu' so với bản sao 'nông' phụ thuộc vào định nghĩa của bạn hay không. – bames53

Trả lời

62

Bạn đang sao chép sâu bất cứ khi nào bạn sao chép vectơ. Nhưng nếu vector của bạn là một vector của con trỏ bạn đang nhận được bản sao của con trỏ, không phải là giá trị được chỉ ra

Ví dụ:

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 Tôi sẽ xem ví dụ thứ hai là bản sao nông. 'int * a, * b; a = b; // Shallow copy'. Trong trường hợp các vectơ nữa, chúng ta có đang làm một cái gì đó như thế này không? BTW, de * e * p của nó và không deap :) – Mahesh

+3

Đôi khi tôi thấy các thuật ngữ này gây nhầm lẫn khi tôi thấy chúng được sử dụng khác nhau, trong các bài viết khác nhau. Người ta có thể nói, trong trường hợp con trỏ, chúng là bản sao nông; cả hai dường như là chính xác, tùy thuộc vào cách bạn giải thích chúng. – Nawaz

+5

Sự nhầm lẫn có thể xuất phát từ sự khác biệt còn thiếu giữa "con trỏ" và "con trỏ". Con trỏ chỉ là các đối tượng bình thường, và chúng thực sự được sao chép chính xác theo cách mà người ta mong đợi. Đó là điểm * mà mọi người đang bối rối. –

1

Vector sẽ thay đổi kích thước để có đủ không gian cho các đối tượng. Sau đó nó sẽ lặp qua các đối tượng và gọi toán tử sao chép mặc định cho mọi đối tượng.

Bằng cách này, bản sao của vectơ là 'sâu'. Bản sao của mỗi đối tượng trong vectơ là bất cứ điều gì được định nghĩa cho toán tử sao chép mặc định.

Trong ví dụ ... Đây là mã 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; 
} 

Đây là mã TỐT HƠN:

#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

Tốt hơn, vẫn, sẽ là Quy tắc Năm. :) (Bạn đã sử dụng Quy tắc Ba cũ hơn) – Arafangion

Các vấn đề liên quan