Empty base optimization
Permet à la taille d'un sous-objet de base vide d'être nulle.
Table des matières |
Explication
La taille de tout
objet
ou sous-objet membre doit être d'au moins 1 même si le type est une
classe vide
(c'est-à-dire une classe ou structure sans membres de données non statiques),
(sauf avec
[[
no_unique_address
]]
, voir ci-dessous)
(depuis C++20)
afin de garantir que les adresses d'objets distincts du même type soient toujours distinctes.
Cependant, les sous-objets de classe de base ne sont pas soumis à cette contrainte et peuvent être complètement optimisés dans la disposition de l'objet :
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)); }
` et `` n'a pas été modifié
- Les termes spécifiques C++ (struct, static_assert, sizeof, etc.) conservés en anglais
L'optimisation de base vide est interdite si l'une des classes de base vides est également le type ou la base du type du premier membre de données non statique, car les deux sous-objets de base de même type doivent avoir des adresses différentes dans la représentation de l'objet du type le plus dérivé.
Un exemple typique d'une telle situation est l'implémentation naïve de std::reverse_iterator (dérivée de la classe de base vide std::iterator ), qui contient l'itérateur sous-jacent (également dérivé de std::iterator ) comme son premier membre de données non statique.
struct Base {}; // classe vide struct Derived1 : Base { int i; }; struct Derived2 : Base { Base c; // Base, occupe 1 octet, suivi du remplissage pour i int i; }; struct Derived3 : Base { Derived1 c; // dérivé de Base, occupe sizeof(int) octets int i; }; int main() { // l'optimisation de base vide ne s'applique pas, // la base occupe 1 octet, le membre Base occupe 1 octet // suivi de 2 octets de remplissage pour satisfaire les exigences d'alignement de int static_assert(sizeof(Derived2) == 2*sizeof(int)); // l'optimisation de base vide ne s'applique pas, // la base prend au moins 1 octet plus le remplissage // pour satisfaire l'exigence d'alignement du premier membre (dont // l'alignement est le même que int) static_assert(sizeof(Derived3) == 3*sizeof(int)); }
|
L'optimisation de base vide est
requise
pour les
StandardLayoutType
s
afin de maintenir l'exigence selon laquelle le pointeur vers un objet de mise en page standard, converti à l'aide de
|
(depuis C++11) |
|
Les sous-objets membres vides sont autorisés à être optimisés tout comme les bases vides s'ils utilisent l'attribut
Exécuter ce code
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)); } |
(depuis C++20) |
Notes
L'optimisation de base vide est couramment utilisée par les classes de la bibliothèque standard compatibles avec les allocateurs (
std::vector
,
std::function
,
std::shared_ptr
, etc.) pour éviter d'occuper un espace de stockage supplémentaire pour son membre allocateur si celui-ci est sans état. Ceci est réalisé en stockant l'un des membres de données requis (par exemple,
begin
,
end
, ou
capacity
pointer pour le
vector
) dans un équivalent de
boost::compressed_pair
avec l'allocateur.
Dans MSVC, l'optimisation des classes de base vides n'est pas entièrement conforme aux exigences standard ( Pourquoi l'optimisation des classes de base vides (EBO) ne fonctionne-t-elle pas dans MSVC ? ).
Références
- Norme C++23 (ISO/CEI 14882:2024) :
-
- 7.6.10 Opérateurs d'égalité [expr.eq]
-
- 7.6.2.5 Sizeof [expr.sizeof]
-
- 11 Classes [class]
-
- 11.4 Membres de classe [class.mem]
- Norme C++20 (ISO/CEI 14882:2020) :
-
- 7.6.10 Opérateurs d'égalité [expr.eq]
-
- 7.6.2.4 Sizeof [expr.sizeof]
-
- 11 Classes [class]
-
- 11.4 Membres de classe [class.mem]
- Norme C++17 (ISO/CEI 14882:2017) :
-
- 8.10 Opérateurs d'égalité [expr.eq]
-
- 8.3.3 Sizeof [expr.sizeof]
-
- 12 Classes [class]
-
- 12.2 Membres de classe [class.mem]
- Norme C++14 (ISO/CEI 14882:2014) :
-
- 5.10 Opérateurs d'égalité [expr.eq]
-
- 5.3.3 Sizeof [expr.sizeof]
-
- 9 Classes [class]
-
- 9.2 Membres de classe [class.mem]
- Norme C++11 (ISO/CEI 14882:2011) :
-
- 5.10 Opérateurs d'égalité [expr.eq] (p: 2)
-
- 5.3.3 Sizeof [expr.sizeof] (p: 2)
-
- 9 Classes [class] (p: 4,7)
-
- 9.2 Membres de classe [class.mem] (p: 20)
- Norme C++98 (ISO/CEI 14882:1998) :
-
- 5.10 Opérateurs d'égalité [expr.eq] (p : 2)
-
- 5.3.3 Sizeof [expr.sizeof] (p : 2)
-
- 9 Classes [class] (p : 3)
Liens externes
| More C++ Idioms/Empty Base Optimization — Un wikibook |