Empty base optimization
빈 기본 하위 객체의 크기를 0으로 허용합니다.
목차 |
설명
모든
객체
또는 멤버 하위 객체의 크기는 해당 유형이 빈
클래스 유형
(즉, 비정적 데이터 멤버가 없는 클래스 또는 구조체)인 경우에도 최소 1이어야 합니다,
(
[[
no_unique_address
]]
를 사용하지 않는 한, 아래 참조)
(C++20부터)
동일한 유형의 서로 다른 객체들의 주소가 항상 구별된다는 것을 보장하기 위함입니다.
그러나 기본 클래스 하위 객체는 이러한 제약을 받지 않으며, 객체 레이아웃에서 완전히 최적화되어 제거될 수 있습니다:
struct Base {}; // empty class struct Derived1 : Base { int i; }; int main() { // the size of any object of empty class type is at least 1 static_assert(sizeof(Base) >= 1); // empty base optimization applies static_assert(sizeof(Derived1) == sizeof(int)); }
빈 기본 클래스 최적화는 빈 기본 클래스 중 하나가 첫 번째 비정적 데이터 멤버의 타입이거나 그 타입의 기본 클래스인 경우 금지됩니다. 왜냐하면 동일한 타입의 두 기본 하위 객체는 가장 파생된 타입의 객체 표현 내에서 서로 다른 주소를 가져야 하기 때문입니다.
이러한 상황의 전형적인 예는 빈 베이스 std::iterator 에서 파생된 std::reverse_iterator 의 나이브 구현으로, 이는 기본 반복자(역시 std::iterator 에서 파생됨)를 첫 번째 비정적 데이터 멤버로 보유합니다.
struct Base {}; // empty class struct Derived1 : Base { int i; }; struct Derived2 : Base { Base c; // Base, occupies 1 byte, followed by padding for i int i; }; struct Derived3 : Base { Derived1 c; // derived from Base, occupies sizeof(int) bytes int i; }; int main() { // empty base optimization does not apply, // base occupies 1 byte, Base member occupies 1 byte // followed by 2 bytes of padding to satisfy int alignment requirements static_assert(sizeof(Derived2) == 2*sizeof(int)); // empty base optimization does not apply, // base takes up at least 1 byte plus the padding // to satisfy alignment requirement of the first member (whose // alignment is the same as int) static_assert(sizeof(Derived3) == 3*sizeof(int)); }
|
빈 베이스 최적화는
필수적입니다
StandardLayoutType
s
에 대해, 표준 레이아웃 객체의 포인터가
|
(C++11부터) |
|
빈 멤버 서브오브젝트는
이 코드 실행
struct Empty {}; // empty class struct X { int i; [[no_unique_address]] Empty e; }; int main() { // the size of any object of empty class type is at least 1 static_assert(sizeof(Empty) >= 1); // empty member optimized out: static_assert(sizeof(X) == sizeof(int)); } |
(C++20부터) |
참고 사항
빈 베이스 최적화는 할당자 인식 표준 라이브러리 클래스들(
std::vector
,
std::function
,
std::shared_ptr
등)에서 할당자가 상태를 가지지 않는 경우 해당 할당자 멤버가 추가 저장 공간을 차지하지 않도록 하기 위해 흔히 사용됩니다. 이는 필요한 데이터 멤버 중 하나(예:
begin
,
end
, 또는
vector
의
capacity
포인터)를 할당자와 함께
boost::compressed_pair
의 동등한 구조에 저장함으로써 달성됩니다.
MSVC에서 빈 기본 클래스 최적화는 표준 요구 사항과 완전히 호환되지 않습니다 ( Why is the empty base class optimization (EBO) is not working in MSVC? ).
참고문헌
- C++23 표준 (ISO/IEC 14882:2024):
-
- 7.6.10 동등 연산자 [expr.eq]
-
- 7.6.2.5 Sizeof [expr.sizeof]
-
- 11 클래스 [class]
-
- 11.4 클래스 멤버 [class.mem]
- C++20 표준(ISO/IEC 14882:2020):
-
- 7.6.10 동등 연산자 [expr.eq]
-
- 7.6.2.4 Sizeof [expr.sizeof]
-
- 11 클래스 [class]
-
- 11.4 클래스 멤버 [class.mem]
- C++17 표준(ISO/IEC 14882:2017):
-
- 8.10 동등 연산자 [expr.eq]
-
- 8.3.3 Sizeof [expr.sizeof]
-
- 12 클래스 [class]
-
- 12.2 클래스 멤버 [class.mem]
- C++14 표준(ISO/IEC 14882:2014):
-
- 5.10 동등 연산자 [expr.eq]
-
- 5.3.3 Sizeof [expr.sizeof]
-
- 9 클래스 [class]
-
- 9.2 클래스 멤버 [class.mem]
- C++11 표준 (ISO/IEC 14882:2011):
-
- 5.10 동등 연산자 [expr.eq] (p: 2)
-
- 5.3.3 Sizeof [expr.sizeof] (p: 2)
-
- 9 클래스 [class] (p: 4,7)
-
- 9.2 클래스 멤버 [class.mem] (p: 20)
- C++98 표준 (ISO/IEC 14882:1998):
-
- 5.10 동등 연산자 [expr.eq] (p: 2)
-
- 5.3.3 Sizeof [expr.sizeof] (p: 2)
-
- 9 클래스 [class] (p: 3)
외부 링크
| More C++ Idioms/Empty Base Optimization — 위키책 |