Empty base optimization
Ermöglicht, dass die Größe eines leeren Basis-Subobjekts null sein kann.
Inhaltsverzeichnis |
Erklärung
Die Größe jedes
Objekts
oder Mitgliedsunterobjekts muss mindestens 1 betragen, selbst wenn der Typ ein leerer
Klassentyp
ist (d.h. eine Klasse oder Struktur ohne nicht-statische Datenelemente),
(sofern nicht mit
[[
no_unique_address
]]
, siehe unten)
(seit C++20)
um garantieren zu können, dass die Adressen verschiedener Objekte desselben Typs stets unterschiedlich sind.
Allerdings sind Basisklassen-Subobjekte nicht so eingeschränkt und können vollständig aus dem Objektlayout optimiert werden:
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)); }
Die Optimierung leerer Basisklassen ist untersagt, wenn eine der leeren Basisklassen auch der Typ oder die Basis des Typs des ersten nicht-statischen Datenelements ist, da die beiden Basis-Subobjekte desselben Typs unterschiedliche Adressen innerhalb der Objektrepräsentation des abgeleitetesten Typs haben müssen.
Ein typisches Beispiel für eine solche Situation ist die naive Implementierung von std::reverse_iterator (abgeleitet von der leeren Basisklasse std::iterator ), die den zugrundeliegenden Iterator (ebenfalls abgeleitet von std::iterator ) als ihr erstes nicht-statisches Datenelement speichert.
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)); }
|
Die Optimierung leerer Basisklassen ist
erforderlich
für
StandardLayoutType
s
, um die Anforderung aufrechtzuerhalten, dass der Zeiger auf ein Standard-Layout-Objekt, konvertiert mittels
|
(since C++11) |
|
Leere Mitgliedssubobjekte dürfen genauso wie leere Basen optimiert werden, wenn sie das Attribut
Code ausführen
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)); } |
(seit C++20) |
Hinweise
Die leere Basisoptimierung wird häufig von allocator-aware Standardbibliotheksklassen verwendet (
std::vector
,
std::function
,
std::shared_ptr
, etc.), um keinen zusätzlichen Speicherplatz für ihr Allokator-Mitglied zu belegen, falls der Allokator zustandslos ist. Dies wird erreicht, indem eines der erforderlichen Datenmitglieder (z.B.
begin
,
end
, oder
capacity
-Zeiger für den
vector
) in einem Äquivalent von
boost::compressed_pair
mit dem Allokator gespeichert wird.
In MSVC ist die Empty-Base-Optimierung nicht vollständig konform mit den Standardanforderungen ( Why is the empty base class optimization (EBO) is not working in MSVC? ).
Referenzen
- C++23-Standard (ISO/IEC 14882:2024):
-
- 7.6.10 Gleichheitsoperatoren [expr.eq]
-
- 7.6.2.5 Sizeof [expr.sizeof]
-
- 11 Klassen [class]
-
- 11.4 Klassenmitglieder [class.mem]
- C++20-Standard (ISO/IEC 14882:2020):
-
- 7.6.10 Gleichheitsoperatoren [expr.eq]
-
- 7.6.2.4 Sizeof [expr.sizeof]
-
- 11 Klassen [class]
-
- 11.4 Klassenmember [class.mem]
- C++17-Standard (ISO/IEC 14882:2017):
-
- 8.10 Gleichheitsoperatoren [expr.eq]
-
- 8.3.3 Sizeof [expr.sizeof]
-
- 12 Klassen [class]
-
- 12.2 Klassenmitglieder [class.mem]
- C++14-Standard (ISO/IEC 14882:2014):
-
- 5.10 Gleichheitsoperatoren [expr.eq]
-
- 5.3.3 Sizeof [expr.sizeof]
-
- 9 Klassen [class]
-
- 9.2 Klassenmitglieder [class.mem]
- C++11-Standard (ISO/IEC 14882:2011):
-
- 5.10 Gleichheitsoperatoren [expr.eq] (S.: 2)
-
- 5.3.3 Sizeof [expr.sizeof] (S.: 2)
-
- 9 Klassen [class] (S.: 4,7)
-
- 9.2 Klassenmitglieder [class.mem] (S.: 20)
- C++98 Standard (ISO/IEC 14882:1998):
-
- 5.10 Gleichheitsoperatoren [expr.eq] (S: 2)
-
- 5.3.3 Sizeof [expr.sizeof] (S: 2)
-
- 9 Klassen [class] (S: 3)
Externe Links
| More C++ Idioms/Empty Base Optimization — Ein Wikibook |