2010-10-22 21 views
5

OK. Chúng tôi biết mã sau không thể được biên dịch.Trong hàm vận hành gán, mảng là memcpy hoàn toàn

char source[1024]; 
char dest[1024]; 
// Fail. Use memcpy(dest, source, sizeof(source)); instead. 
dest = source; 

Nhưng, mã sau có thể được biên dịch và hoạt động chính xác.

class A { 
    char data[1024]; 
}; 
A source; 
B dest; 
dest = source; 

Tôi đã tự hỏi, trong chức năng gán toán tử, mảng có được ghi nhớ ngầm không?

Sau đây là mã kiểm tra hoàn chỉnh.


#include <cstdio> 
#include <memory> 

class A { 
public: 
    char data[1024]; 
}; 

int main() { 
    { 
     A source; 
     A dest; 

     // Initialization 
     char *data = "hello world"; 
     memcpy (source.data, data, strlen(data) + 1); 

     printf ("source.data = %s\n", source.data); 
     printf ("address source.data = %x\n", source.data); 

     // Works! Does this in the operator assignment function, memcpy is 
     // being performed implicitly on array. 
     dest = source; 

     printf ("dest.data = %s\n", dest.data); 
     printf ("address dest.data = %x\n", dest.data); 
    } 

    { 
     char source[1024]; 
     char dest[1024]; 

     // Initialization 
     char *data = "hello world"; 
     memcpy (source, data, strlen(data) + 1); 

     printf ("source = %s\n", source); 
     printf ("address source = %x\n", source); 

     // '=' : left operand must be l-value 
     // dest = source; 
     // Works with memcpy. 
     memcpy(dest, source, sizeof(source)); 

     printf ("dest = %s\n", dest); 
     printf ("address dest = %x\n", dest); 
    } 

    getchar(); 
} 

//RESULT : 
//source.data = hello world 
//address source.data = 12fb60 
//dest.data = hello world 
//address dest.data = 12f758 
//source = hello world 
//address source = 12f344 
//dest = hello world 
//address dest = 12ef3c 
+0

Đã có rất nhiều cuộc thảo luận về lý do tại sao trường hợp này xảy ra trong [Tại sao C++ hỗ trợ phân bổ thành viên theo mảng trong cấu trúc nhưng không thường?] (Http://stackoverflow.com/questions/3437110/why-does -c-support-memberwise-assignment-of-mảng-trong-structs-nhưng-không-gen) –

+0

Trái ngược với std :: string, eh? –

Trả lời

2

trình biên dịch tạo ra bản sao-ctor/phân-op là Bitwise-bản sao nếu không có sao chép ctor/phân-op tìm thấy cho các phần tử con.

Chỉnh sửa:
Đây là trường hợp kiểm tra đã sửa đổi hiển thị khái niệm.

#include <cstdio> 
#include <memory> 

class someElement 
{ 
public: 
    someElement() : theData(0) {} 
    // Intentionally copy-edit 
    someElement(const someElement& src) : theData(src.theData + 1) {} 
    ~someElement(){} 

    someElement& operator=(const someElement& rhs) 
    { 
     theData = rhs.theData - 1; 
     return *this; 
    } 

    char theData; 
}; 

class A { 
public: 
    someElement data[1024]; 
}; 

int main() { 
    { 
     A source; 
     A dest; 

     // Initialization 
     char *data = "hello world"; 
     memcpy (source.data, data, strlen(data) + 1); 

     printf ("source.data = %s\n", source.data); 
     printf ("address source.data = %x\n", source.data); 

     // Works! Does this in the operator assignment function, memcpy is 
     // being performed implicitly on array. 
     dest = source; 

     printf ("dest.data = %s\n", dest.data); 
     printf ("address dest.data = %x\n", dest.data); 
    } 

    { 
     someElement source[1024]; 
     someElement dest[1024]; 

     // Initialization 
     char *data = "hello world"; 
     memcpy (source, data, strlen(data) + 1); 

     printf ("source = %s\n", source); 
     printf ("address source = %x\n", source); 

     // '=' : left operand must be l-value 
     // dest = source; 
     // Works with memcpy. 
     memcpy(dest, source, sizeof(source)); 

     printf ("dest = %s\n", dest); 
     printf ("address dest = %x\n", dest); 
    } 

    getchar(); 
} 
+0

Sao chép bit được thực hiện trên mảng như thế nào? Bất kỳ nguồn tham chiếu nào? –

+0

@Yan Cheng CHEOK: toán tử = được gọi cho mỗi phần tử lần lượt. Nó là loại đệ quy – Chubsdad

4

operator=, nếu không được triển khai một cách rõ ràng, thực hiện sao chép thành viên nội dung của lớp học. Đối với mảng đóng gói của bạn, điều này sẽ có tác dụng nhưng cần phải có sự chăm sóc chung để đảm bảo sao chép sâu đúng cách dữ liệu của lớp.

+0

lưu ý rằng nó không phải là bitwise sao chép nếu thành viên có nhiệm vụ-op. – YeenFei

+2

No. Nó thực hiện một bản sao thành viên khôn ngoan. Điều này là cần thiết vì các kiểu lồng nhau có thể có toán tử riêng của họ =() ở bất kỳ độ sâu nào trong hệ thống phân cấp lồng nhau. Toán tử =() của chúng có thể có bất kỳ số lượng tác dụng phụ nào ngoài phạm vi bit mà bản sao bitmap sẽ ảnh hưởng. Những tác dụng phụ này được đảm bảo xảy ra. Vì vậy, không, bản sao không phải là bitwise. –

+0

@Eric - cảm ơn, đã cập nhật văn bản và câu trả lời thay thế được upvoted –

9

Trích dẫn này từ Trợ giúp chuẩn? Nó yên tĩnh tự giải thích

Xin lỗi, đã xóa câu trả lời trước đó của tôi liên quan đến nhà xây dựng sao chép và không phải là nhà điều hành gán bản sao.

$ 12,8/30-

Các ngầm xác định nhiệm vụ sao chép điều hành cho một tổ chức phi đoàn lớp X Thực hiện sao chép ngầm giao subobjects của nó. Các cơ sở trực tiếp các lớp X được chỉ định trước tiên, theo thứ tự thứ tự khai báo của chúng trong danh sách -specifier-spec, và sau đó thành viên dữ liệu không tĩnh ngay lập tức của X được chỉ định, theo thứ tự trong đó đã được khai báo trong định nghĩa lớp học . Mỗi subobject được gán theo cách thức phù hợp với loại của nó:

- nếu subobject là loại lớp, toán tử gán bản sao cho lớp được sử dụng (như thể bởi trình độ chuyên môn rõ ràng , đó là, bỏ qua bất kỳ chức năng ghi đè ảo có thể trong các lớp học có nguồn gốc khác);

- nếu subobject là một mảng, mỗi phần tử được được giao, theo cách thức phù hợp để các loại nguyên tố;

- nếu subobject thuộc loại vô hướng, thì được sử dụng toán tử gán được cài sẵn.

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