2013-01-16 25 views
5

thể trùng lặp:
Classes store data members in sequential memory?biến lớp - liên kết

Chỉ muốn hỏi tại sao sau đây là đúng:

template<class T> 
class Vec3 { 
public: 
    // values 
    T x,y,z; 

    // returns i-th komponent (i=0,1,2) (RHS array operator) 
    const T operator[] (unsigned int i) const { 
    return *(&x+i); 
    } 
} 

hay nói cách khác: Tại sao nó luôn đảm bảo rằng x, y và z luôn là các đơn vị sizeof (T) tách biệt trong bộ nhớ. Có thể không bao giờ có lỗ phân mảnh ở giữa hai trong số những biến thể đó, do đó cho phép toán tử này trả về một giá trị sai?

+0

Nếu bạn cần lập chỉ mục, tại sao không làm cho nó 'mẫu lớp Vector3 {public: std :: mảng xs; }; '? – Fanael

Trả lời

6

Nó được không đảm bảo rằng x, yz luôn sizeof(T) đơn vị ngoài trong bộ nhớ. Có thể có các byte đệm được thêm vào giữa.
Nó được để lại dưới dạng chi tiết triển khai.
Điều duy nhất được đảm bảo là sẽ không có đệm giữa đầu lớp/cấu trúc và thành viên đầu tiên của nó cho cấu trúc/lớp học POD.

Không đảm bảo rằng việc triển khai operator[] trong mã của bạn sẽ luôn hoạt động.

tham khảo:
C++ 11: 9,2 thành viên Class [class.mem]

14) không tĩnh dữ liệu thành viên của một (phi đoàn) lớp học với sự kiểm soát truy cập cùng (khoản 11) được phân bổ như vậy rằng các thành viên sau này có địa chỉ cao hơn trong một đối tượng lớp. Thứ tự phân bổ dữ liệu không tĩnh thành viên có quyền kiểm soát truy cập khác nhau không được chỉ định (11). Yêu cầu căn chỉnh thực hiện có thể khiến hai thành viên lân cận không được phân bổ ngay sau mỗi khác; vì vậy có thể yêu cầu cho không gian để quản lý các chức năng ảo (10.3) và các lớp cơ sở ảo (10.1).

+0

Ý của bạn là gì "Nó bị bỏ sót dưới dạng chi tiết triển khai". –

+0

Ngay cả việc bảo đảm liên quan đến địa chỉ của thành viên đầu tiên chỉ hợp lệ đối với cấu trúc POD.(Hoặc có thể cho các cấu trúc tương thích bố trí trong C++ 11.) –

+0

@AdamMagaluk: Nó có nghĩa là trình biên dịch được tự do thêm nhiều byte đệm cần thiết ở giữa các thành viên lớp/cấu trúc. Tiêu chuẩn không quy định bất kỳ yêu cầu cụ thể nào về vấn đề này. –

0

Để tránh lỗ phân mảnh bạn có thể kiểm soát sự liên kết theo cách này:

#ifdef compiling_with_msvc 
#pragma pack(1) 
#endif 
template<class T> 
class Vec3 { 
public: 
    // values 
    T x,y,z; 

    // returns i-th komponent (i=0,1,2) (RHS array operator) 
    const T operator[] (unsigned int i) const { 
     return *(&x+i); 
    } 
#ifdef compiling_with_gcc 
}__attribute__((packed)); 
#else 
}; 
#endif 

Nếu bạn có thể sử dụng một C++11 compiler bạn có thể kiểm soát sự liên kết trong một standard way.

Nhưng nếu bạn không quan tâm đến các đại diện bộ nhớ của lớp, suy nghĩ về sử dụng một union:

template <typename T> 
union Vec3 
{ 
    T x, y, z; 
    struct 
    { 
     T value[3]; 
    } vector; 
}; 

Với sự kết hợp, bạn không cần phải quan tâm đến sự liên kết để acces mỗi thành phần với []:

Vec3<unsigned int> v3; 

v3.vector.value[0] = 1; 
v3.vector.value[1] = 2; 
v3.vector.value[2] = 3; 
+0

Có thực sự được chỉ định ở đâu đó, trong giải pháp công đoàn của bạn, các trường sẽ được căn chỉnh (ví dụ: x và giá trị [0], y và giá trị [1])? Nó làm cho * ý nghĩa *, nhưng điều này thực sự được chỉ định/bảo đảm bất cứ nơi nào? – rmhartog

+0

Có, 'x' và' giá trị [0] ',' y' và 'giá trị [1]' ... sẽ có cùng địa chỉ ... nhưng tôi không thể garantee rằng giữa 'x' <->' y', ' value [0] '<->' value [1] 'bạn sẽ tìm thấy các byte đệm; nó sẽ phụ thuộc vào kiểu dữ liệu, căn chỉnh dữ liệu và điều khiển căn chỉnh của 'union' –

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