2012-02-06 18 views
9

Tôi mới dùng C++ và tìm thấy một tính năng đặc biệt trong C++. Tôi thấy kích thước của một trống là 1 byte, tôi đã làm một số nghiên cứu và phát hiện ra rằng được thực hiện bởi vì mọi đối tượng phải có một địa chỉ riêng biệt. Nhưng tôi muốn biết nội dung của 1 byte đó được đặt là gì. Tôi biết nó không giữ con trỏ "này" nhưng nó là một byte giả hoặc là có thực sự một số nội dung?Lớp C++ lớp trống 1 byte

Trả lời

11

Không có nội dung. Nó chỉ là một byte giả.

Mọi class hoặc struct phải có sizeof lớn hơn 0, hành vi của bạn. Dự kiến ​​và được yêu cầu bởi tiêu chuẩn.

+0

Thực tế trong g ++, có thể xác định một lớp có kích thước 0. Xem câu trả lời của tôi. – TrueY

0

Đó là một byte giả - hàm tạo và hàm hủy sẽ không đáng kể, không có "dữ liệu được lưu trữ".

2

Bạn có thể sử dụng trình gỡ lỗi hoặc một cái gì đó đơn giản như printf("%x", *(unsigned char *)&myobj); để xem nội dung của byte. Tôi đã không đọc các đặc điểm kỹ thuật C + + nhưng tôi sẽ đoán rằng nội dung của byte là không xác định để hành vi phụ thuộc vào trình biên dịch và hệ điều hành của bạn.

3

byte không chứa gì, nó ở đó để làm cho một số hành vi khác đẹp hơn. Ví dụ xem xét trường hợp của các lớp trống có trong một lớp khác.

class Empty 
{ }; 

class TwoEmpties 
{ 
    Empty a; 
    Empty b; 
}; 

Bạn có thể muốn các địa chỉ của hai thành viên, &TwoEmpties::a&TwoEmpties::b, phải khác nhau. Đối với điều này xảy ra họ phải có kích thước> 1. (hoặc trình biên dịch sẽ phải thêm đệm giữa chúng, mà lần lượt sẽ phức tạp các quy tắc cho khi nào và ở đâu trình biên dịch có thể thêm đệm vào lớp.)

+0

Phải thừa nhận rằng bạn ** không ** thường muốn địa chỉ của hai thành viên. Thật vậy, trong phần lớn các trường hợp, bạn không ** quan tâm ** về địa chỉ của hai thành viên. Quy tắc này phục vụ cho một số ít trường hợp sử dụng, mặc dù chúng được đánh giá là đủ quan trọng để ủy thác nó. –

+0

@MatthieuM. đã đồng ý. Cố định từ ngữ hơi –

7

Nó được ủy quyền theo tiêu chuẩn, các đối tượng khác nhau cùng loại phải có địa chỉ khác nhau. Điều này lần lượt đảm bảo rằng đối với bất kỳ đối tượng T, T* hoạt động như một định danh rõ ràng của đối tượng này (đối với loại này).

Được cấp, bạn không thường xuyên cần biết hai đối tượng có thực sự giống nhau hay không, nhưng đôi khi (được cấp quyền truy cập cấp thấp C++), hoặc là cần thiết hoặc chỉ đơn giản là thuận tiện.

Do đó, quy định rằng không có đối tượng nào phải có kích thước bằng không.

Có một ngoại lệ cho quy tắc này mặc dù: khi sử dụng một lớp rỗng như một lớp cơ sở, trình biên dịch có thể chọn để áp dụng các Optimization Rỗng cơ sở (EBO) là một số trường hợp, ví dụ:

struct Empty {}; 

struct Slim: Empty { 
    int a; 
}; 

static_assert(sizeof(Slim) == sizeof(int), ""); 

Nói chung, kích thước của lớp cơ sở được thêm vào, nhưng trong trường hợp cụ thể này, không cần thiết. Tuy nhiên các quy tắc mà hai đối tượng khác nhau của cùng loại không bao giờ nên có cùng địa chỉ vẫn áp dụng, và như vậy:

struct Fat: Empty { 
    Empty e; 
}; 

static_assert(sizeof(Fat) > sizeof(Empty), ""); 

EBO là lý do chính cho việc sử dụng private thừa kế trong các tình huống mẫu. Ví dụ:

template <typename Allocator> 
class MyClass: private Allocator { 
}; 

Bằng cách này, nếu chỉ ra rằng Allocator là một lớp trống, sẽ không có bất kỳ chi phí nào.Nói chung, nó là như vậy, thường được sử dụng cho chính sách, ví dụ như các vị từ bạn vượt qua để map.

1

Một empty class has a sizeof 1 vì khi đối tượng của lớp đó được tạo ra họ sẽ được lưu trữ trên cùng một vị trí trong bộ nhớ nếu size = 0.

Giả sử rằng khi bạn tạo một đối tượng address is 1000.

Nếu kích thước của class is 0 do đó kích thước của object must be 0 là tốt.

(therefore, object is located at 1000+0=1000) 

Vì vậy, bây giờ nếu đối tượng khác được thực hiện,

Add. of 2nd object=1000+0th location 

Cả hai đối tượng có cùng một địa chỉ và đây là hành vi không xác định và không nên xảy ra như sẽ có sự mơ hồ mà đối tượng đang được đề cập đến .

Do đó empty classes are given a byte of memory để ngăn chặn tình huống như vậy xảy ra.

0

Tất cả các câu trả lời trên là không đúng theo hiểu biết của tôi. Câu trả lời đúng là theo mặc định 4 chức năng sẵn có được gọi khi đối tượng của lớp được tạo ra đó là

  1. Mặc định constructor

  2. Mặc định destructor

  3. Sao chép constructor

  4. bài tập quá tải điều hành

do đó kích thước của lớp rỗng là 1byte, Ví dụ: thử này

#include<iostream> 
using namespace std; 
class Test 
{ 
}; 
int main() 
{ 
Test t; 
cout<< "size of empty class is "<<sizeof(t); 
} 
0

tôi phải đối mặt với vấn đề tương tự và có vẻ như rằng người ta có thể xác định một lớp học với số không dài với một mẹo nhỏ. Tôi không biết nếu nó chỉ là vì g ++, nhưng xem đoạn mã sau:

struct ONE {}; 
struct ZERO { char x[0]; }; 

int main() { 
    cout << sizeof(ONE) << ", " << sizeof(ZERO) << endl; 

    ONE* po1 = new ONE; 
    ONE* po2 = new ONE; 
    cout << po1 << ", " << po2 << endl; 

    ZERO* pz1 = new ZERO; 
    ZERO* pz2 = new ZERO; 
    cout << pz1 << ", " << pz2 << endl; 
} 

Đầu ra là:

1, 0 
0xe4f010, 0xe4f030 
0xe4f050, 0xe4f070 

Vì vậy, kích thước của một lớp rỗng là một (theo Tiêu chuẩn C++), nhưng nếu nó chỉ có trường mảng có độ dài bằng không thì kích thước sẽ bằng 0. Nếu một lớp thực sự mới có kích thước bằng không được cấp phát trên heap với new một địa chỉ hợp lệ được trả về và nếu được phân bổ nhiều lần con trỏ của chúng trỏ đến các địa chỉ bộ nhớ khác nhau.

+0

Vâng, một mảng có độ dài bằng không tĩnh được định dạng không đúng. – Deduplicator

+0

@Deduplicator Có thể bạn đã đúng, nhưng tôi đã thấy các cấu trúc như vậy (có char [0] như là một mục cuối cùng) nhiều lần. Vì vậy, nó được lan truyền bằng cách nào đó. – TrueY

+0

struct { chiều dài int; char d [0]; }; Độ dài bản ghi biến * lừa * (mặc dù tôi không thích gọi bất cứ thứ gì mạnh mẽ như vậy 'lừa' :)). –