2010-03-18 48 views
7

Kích thước của một lớp không có thành viên dữ liệu được trả về là 1 byte, mặc dù có một con trỏ 'this' ẩn này được khai báo. Không nên kích thước trả về là 4 byte (trên một máy 32 bit)? Tôi đã xem các bài báo chỉ ra rằng con trỏ 'này' không được tính để tính kích thước của đối tượng. Nhưng tôi không thể hiểu được lý do cho việc này. Ngoài ra, nếu bất kỳ hàm thành viên nào được khai báo là ảo, kích thước của lớp bây giờ được trả về là 4 byte. Điều này có nghĩa rằng vptr được tính để tính kích thước của đối tượng. Tại sao vptr được xem xét và con trỏ 'this' này bị bỏ qua để tính toán kích thước của đối tượng?Kích thước của một lớp với con trỏ 'này'

+0

bản sao: http://stackoverflow.com/questions/621616/c-what-is-the-size-of-an-object-of-an-empty-class http://stackoverflow.com/questions/2362097/empty-class-in-c –

Trả lời

6

Con trỏ this không phải là thành viên của lớp. Nó chỉ là một cấu trúc được sử dụng trong các phương thức thuộc lớp để tham chiếu đến cá thể hiện tại.

Nếu bạn có một lớp học như thế này:

class IntPair 
{ 
public: 
    IntPair(int a, int b) : _a(a), _b(b) { } 

    int sum() const { return _a + _b; } 

public: 
    int _a; 
    int _b; 
}; 

Lớp này chỉ cần không gian cho hai trường hợp của int cho mỗi trường hợp. Khi bạn đã tạo một cá thể và đang chạy phương thức sum(), phương thức đó được gọi với một con trỏ tới cá thể đó, nhưng con trỏ đó luôn xuất phát từ một nơi khác, nó không được lưu trữ trong cá thể đối tượng.

Ví dụ:

IntPair *fib12 = new IntPair(89, 144); 

cout << fib12->sum(); 

Thông báo như thế nào biến đó trở thành con trỏ this được lưu trữ bên ngoài đối tượng, trong phạm vi đã tạo ra nó.

Bạn có thể, trên thực tế, luôn luôn biến đổi một phương pháp như một ở trên vào:

static int sum2(const IntPair* instance) 
{ 
    return instance->_a + instance->_b; 
} 

Nếu ở trên được định nghĩa bên trong lớp (vì vậy nó có thể truy cập các thành viên tư nhân), không có sự khác biệt. Trên thực tế, này là cách các phương thức được triển khai phía sau hiện trường; con trỏ this chỉ là một đối số ẩn cho tất cả các phương thức thành viên.

Cuộc gọi sẽ trở thành:

IntPair* fib12 = new IntPair(89, 144); 

cout << IntPair::sum2(fib12); 
4

'này' không được lưu trữ như là một thành viên dữ liệu trong lớp, nó chỉ là một 'con trỏ' đến thể hiện của lớp. Xem xét nó như là một 'đối số ẩn' được chuyển cho phương thức. Trong thực tế, trên các hệ thống Win32 nó thường được chuyển trong thanh ghi ecx (không phải là eax như tôi nghĩ ban đầu).

Ngay khi bạn có 1 hoặc nhiều phương pháp ảo, ứng dụng của bạn cần có cách để lưu trữ các con trỏ đến các phương thức ảo. Điều này được gọi là vtable, giống hệt với tất cả các cá thể của cùng một lớp. Vì bạn cần biết tại thời gian chạy mà phương thức 'tường minh' để gọi cho 'phương thức ảo' nào một con trỏ tới vtable được lưu trữ trong cá thể lớp. Do đó, vtable-pointer (hoặc vptr) cần 4 byte (hoặc 8 byte trên hệ thống 64 bit).

+1

Tôi nghĩ nó đã được chuyển trong 'ecx'. – Blindy

+0

Rất tiếc, bạn đã đúng. eax được sử dụng cho giá trị trả lại. (Tôi đã chỉnh sửa bài đăng) – Patrick

2

Con trỏ này không được lưu trữ bên trong đối tượng. Không cần phải làm thế. Bạn đã có một con trỏ hoặc một đối tượng để gọi các hàm. Đối với kích thước của 1, tiêu chuẩn C++ reqires rằng các đối tượng distict có địa chỉ riêng biệt.

-1

Kích thước của con trỏ luôn là kích thước của loại con trỏ cần thiết để được lưu trữ trong bộ nhớ.Ví dụ, nếu địa chỉ bộ nhớ của một int là 32 bit trên kiến ​​trúc 64 bit, thì

int a = 10; int * b = & a; sizeof (b); // 32 sizeof (& b); 64

+0

bên cạnh đó sizeof() trả về số byte, không phải bit, sizeof (int *) và sizeof (int **) không thể khác nhau. – PlasmaHH

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