ภาพรวม
ใน C++ Empty Class (ไม่มี Non-Static Data Members) มีขนาดอย่างน้อย 1 Byte เพื่อให้ Object แต่ละตัวมี Address ที่ไม่ซ้ำกัน (Unique Address) ตามกฎของ C++ Standard
ตัวอย่างโค้ด
#include <iostream>
using namespace std;
class Empty {}; // Empty Class
class NonEmpty { // Non-Empty Class
int data;
public:
void func() {}
};
int main() {
Empty e1, e2;
NonEmpty n1, n2;
cout << "Size of Empty class: " << sizeof(Empty) << "\n";
cout << "Size of NonEmpty class: " << sizeof(NonEmpty) << "\n";
cout << "Size of Empty object: " << sizeof(e1) << "\n";
cout << "Size of NonEmpty object: " << sizeof(n1) << "\n";
cout << "\nAddress of e1: " << &e1;
cout << "\nAddress of e2: " << &e2;
cout << "\nAddresses are different: " << (&e1 != &e2) << "\n";
return 0;
}
ผลลัพธ์
Size of Empty class: 1
Size of NonEmpty class: 4
Size of Empty object: 1
Size of NonEmpty object: 4
Address of e1: 0x7ffc1234
Address of e2: 0x7ffc1235
Addresses are different: 1
ทำไมต้องเป็น 1 Byte?
- Unique Address Requirement: C++ Standard กำหนดว่า Object ทุกตัวต้องมี Address ที่แตกต่างกัน (
&obj1 != &obj2) - Array Support: ถ้า Size = 0,
Empty arr[10]จะมีขนาด 0 → ทุก Element ชี้ Address เดียวกัน - Pointer Arithmetic:
ptr + 1ต้องชี้ Object ถัดไปได้
Empty Base Optimization (EBO)
Compiler Optimization ที่ทำให้ Empty Base Class **ไม่ใช้พื้นที่** ใน Derived Class:
class EmptyBase {}; // Size = 1
class Derived : public EmptyBase {
int data; // Size = 4 (ไม่ใช่ 5!)
};
int main() {
cout << sizeof(EmptyBase) << "\n"; // 1
cout << sizeof(Derived) << "\n"; // 4 (EBO Applied!)
}
เงื่อนไข EBO
- Base Class ต้องเป็น Empty (No Non-Static Data Members)
- Derived Class ต้องไม่มี Base Class อื่นที่ Empty และ Type เดียวกัน (No Ambiguity)
- Multiple Inheritance: EBO ทำงานได้หลาย Base ถ้า Type ต่างกัน
ขนาดในกรณีต่างๆ
| ประเภท | ขนาด (Typical 64-bit) | หมายเหตุ |
|---|---|---|
| Empty Class | 1 Byte | Minimum Size |
| Class with int | 4 Bytes | int = 4 bytes |
| Class with int + double | 16 Bytes | Alignment: double ต้อง 8-byte aligned |
| Empty Base + int (EBO) | 4 Bytes | Empty Base ไม่เพิ่ม Size |
| Two Empty Bases (Different Types) | 1 Byte | EBO ทั้งคู่ Overlap ได้ |
| Virtual Function (vptr) | 8 Bytes (64-bit) | Pointer to vtable |
| Virtual Inheritance | +8 Bytes (vbptr) | Virtual Base Pointer |
C++20: [[no_unique_address]]
struct NonEmpty {
int data;
[[no_unique_address]] EmptyBase base; // Force EBO-like behavior for Member
// Size = 4 (แทนที่จะเป็น 8)
};
สรุป
- Empty Class = 1 Byte (Minimum)
- EBO ทำให้ Empty Base Class ไม่เพิ่มขนาด Derived Class
- ใช้ Empty Classes สำหรับ Tags, Policies, Mixins ได้โดยไม่เสีย Memory
[[no_unique_address]](C++20) ขยาย EBO ให้ Member Variables ด้วย