2010-01-25 47 views
17

Tôi biết rằng sizeof là một phép tính thời gian biên dịch, nhưng điều này có vẻ lạ đối với tôi: Trình biên dịch có thể lấy một tên kiểu hoặc một biểu thức (từ đó nó loại trừ loại). Nhưng làm thế nào để bạn xác định một loại trong một lớp học? Có vẻ như cách duy nhất là để vượt qua một biểu hiện, mà có vẻ khá clunky.Tại sao các thành viên cấu trúc phân tích cú pháp không kích thước?

struct X { int x; }; 
int main() { 
    // return sizeof(X::x); // doesn't work 
    return sizeof(X()::x); // works, and requires X to be default-constructible 
} 
+11

Hỗ trợ cho 'sizeof (X :: x)' được bao gồm trong C++ 0x (x http://www.open -std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html). –

+0

@James +1 theo nhận xét của bạn. Câu trả lời của tôi (đã xóa) phải là một bình luận thực sự, bởi vì Tom đã không đề cập đến C++ 0x. Có lẽ anh ta muốn nó trong C++ 98 :) – AraK

+0

Vâng, câu hỏi của tôi là về C++ 98. Tuy nhiên, ngay cả khi tôi xây dựng với '-std = C++ 0x', nó không hoạt động (GCC 4.3.2). Có bất kỳ triển khai trình biên dịch nào hỗ trợ nó chưa? – Tom

Trả lời

27

Một phương pháp thay thế hoạt động mà không cần một constructor mặc định:

return sizeof(((X *)0)->x); 

Bạn có thể bọc này trong một macro để nó đọc tốt hơn:

#define member_sizeof(T,F) sizeof(((T *)0)->F) 
+0

AFAIK, dereferencing con trỏ NULL là hành vi không xác định. Quy tắc đó có áp dụng trong trường hợp này không? – AraK

+5

@AraK: Tôi không nghĩ như vậy: "Toán hạng [của sizeof] là một biểu thức, * không được đánh giá *, hoặc một id kiểu ngoặc đơn" (5.3.3/1; nhấn mạnh của tôi). –

+2

Con trỏ NULL không bao giờ bị bỏ qua. Đây là một hoạt động biên dịch. Nó chỉ đơn giản là để có được trình biên dịch để làm The Right Thing (tm). –

0

gì về offsetof? Có một cái nhìn here. Ngoài ra, hãy xem here, kết hợp cả hai sizeofoffsetof thành macro.

Hy vọng điều này sẽ hữu ích.

+0

Không giúp được gì, bởi vì trình biên dịch (trong khi yêu cầu đặt hàng các phần tử của cấu trúc theo thứ tự được khai báo) là miễn phí để đệm chúng khi thấy cần thiết. – dmckee

+0

dmckee: Oh, Ok..thanks cho đầu vào của bạn! Chúc mừng :) – t0mm13b

10

Dưới đây là một giải pháp mà không có con trỏ null khó chịu dereferencing;)

struct X { int x; }; 

template<class T> T make(); // note it's only a declaration 

int main() 
{ 
    std::cout << sizeof(make<X>().x) << std::endl; 
} 
+0

oh, đó là trixy! – Tom

+1

Bạn không thể nói 'extern T fakeT; sizeof (fakeT.x); '? – MSalters

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