2014-09-13 12 views
8

3.9/2:Tại sao có hạn chế đối với một subobject cấp cơ sở?

Đối với bất kỳ đối tượng (khác hơn là một subobject cơ sở hạng) của trivially copyable loại T, có hoặc không có đối tượng nắm giữ một giá trị hợp lệ của loại T, các byte tiềm ẩn (1.7) tạo thành đối tượng có thể được sao chép vào một mảng char hoặc unsigned char.

3,9/3:

Đối với bất kỳ loại T trivially copyable, nếu hai con trỏ đến T điểm đến đối tượng T riêng biệt obj1 và obj2, nơi không obj1 cũng không obj2 là một subobject cơ sở lớp, nếu các byte cơ bản (1.7) tạo thành obj1 là được sao chép vào obj2, obj2 sau đó sẽ giữ cùng giá trị với obj1.

Tôi hiểu các quy tắc này một cách chính thức, nhưng tôi quan tâm đến những hạn chế như vậy là gì?

+2

Có lẽ do tối ưu hóa cơ sở trống. –

+0

@ T.C. Nó không hoàn toàn rõ ràng. Bạn có thể cung cấp một ví dụ để giải thích? –

+1

@DmitryFucintv Với 'struct T {}; struct D: T {int x; }; ',' sizeof (T) == 1', nhưng trong 'D', lớp con cơ sở có thể có kích thước bằng 0. –

Trả lời

9

Lớp con lớp cơ sở có thể có phần đệm ở cuối được sử dụng bởi lớp dẫn xuất. Với hai lớp,

struct A { 
    int a; 
    char b; 
}; 
struct B : A { 
    char c; 
}; 

hoàn toàn có thể là sizeof(A) == sizeof(B). Nếu chúng bằng nhau, cần phải rõ ràng rằng mọi thứ sẽ bị hỏng nếu bạn chỉ sử dụng memcpy để sao chép tiểu mục phụ A: bạn sẽ không thể ngăn đọc hoặc thậm chí ghi đè giá trị c.

Việc triển khai của bạn có thể hoặc không thể sử dụng lại phần đệm như vậy. Một lý do hợp lệ để thiết kế một ABI nơi đệm là không tái sử dụng là chính xác để đối phó độc đáo với mã mà không, không chính xác, sử dụng memcpy cho subobjects như vậy.

Nhận xét đưa ra ví dụ về các lớp cơ sở trống. Đó là một trường hợp cụ thể trong đó việc triển khai hiện tại rất có khả năng tái sử dụng một byte của lớp cơ sở, nhưng nó không phải là lần duy nhất nó được cho phép.

0

Dưới đây là một ví dụ về giá trị gia screwing do subobjects lớp cơ sở và EBO:

#include <cassert> 
#include <iostream> 

struct Base {}; // empty class 

struct Derived1 : Base { 
public:  
    int i; 
}; 

int main() 
{ 
    // the size of any object of empty class type is at least 1 
    assert(sizeof(Base) == 1); 

    // empty base optimization applies 
    assert(sizeof(Derived1) == sizeof(int)); 

    Base objBase; 
    Derived1 objDerived; 
    objDerived.i = 42; 
    Base& refToobjDerived = objDerived; 

    char buf[sizeof(Base)]; // 1 

    std::memcpy(buf, &objBase, sizeof(Base)); // copy objBase to buf 
    // might do something with buf.. 
    std::memcpy(&refToobjDerived, buf, sizeof(Base)); // EBO! I'm overwriting the int's value! 

    std::cout << objDerived.i; // Screwed 
} 

Example

Nếu bạn làm cho lớp cơ sở non-trivially-copyable, giá trị sẽ không được chạm vào.

Một vấn đề khác như hvd được đánh dấu có thể nằm trong phần đệm bổ sung ở cuối lớp cơ sở được sử dụng để lưu trữ dữ liệu có nguồn gốc.

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