Recherche…
Introduction
Tous les types en C ++ ont un alignement. Ceci est une restriction sur l'adresse mémoire que les objets de ce type peuvent être créés à l'intérieur. Une adresse mémoire est valide pour la création d'un objet si la division de cette adresse par l'alignement de l'objet est un nombre entier.
Les alignements de type sont toujours une puissance de deux (dont 1).
Remarques
La norme garantit les éléments suivants:
- L'exigence d'alignement d'un type est un diviseur de sa taille. Par exemple, une classe avec une taille de 16 octets peut avoir un alignement de 1, 2, 4, 8 ou 16, mais pas de 32. (Si les membres d'une classe ne totalisent que 14 octets, mais que la classe doit avoir un besoin d'alignement) de 8, le compilateur va insérer 2 octets de remplissage pour que la taille de la classe soit égale à 16.)
- Les versions signées et non signées d'un type entier ont la même exigence d'alignement.
- Un pointeur à
void
a la même exigence d'alignement qu'un pointeur surchar
. - Les versions qualifiées cv et non qualifiées CV d'un type ont la même exigence d'alignement.
Notez que si l'alignement existe en C ++ 03, ce n'est qu'en C ++ 11 qu'il est devenu possible d'interroger l'alignement (en utilisant alignof
) et de contrôler l'alignement (en utilisant alignas
).
Interroger l'alignement d'un type
L'exigence d'alignement d'un type peut être interrogée à l'aide du mot clé alignof
tant qu'opérateur unaire. Le résultat est une expression constante de type std::size_t
, c'est-à-dire qu'il peut être évalué au moment de la compilation.
#include <iostream>
int main() {
std::cout << "The alignment requirement of int is: " << alignof(int) << '\n';
}
Sortie possible
Le besoin d'alignement de int est: 4
Si elle est appliquée à un tableau, elle génère l’alignement requis pour le type d’élément. S'il est appliqué à un type de référence, il génère l'exigence d'alignement du type référencé. (Les références elles-mêmes n'ont aucun alignement, car elles ne sont pas des objets.)
Contrôle de l'alignement
Le mot-clé alignas
peut être utilisé pour forcer une variable, un membre de données de classe, une déclaration ou une définition de classe, ou une déclaration ou une définition d'un enum, à avoir un alignement particulier, s'il est pris en charge. Il se présente sous deux formes:
-
alignas(x)
, oùx
est une expression constante, donne à l'entité l'alignementx
, si elle est supportée. -
alignas(T)
, oùT
est un type, donne à l'entité un alignement égal à l'exigence d'alignement deT
, c'est-à-direalignof(T)
, si elle est prise en charge.
Si plusieurs spécificateurs d' alignas
sont appliqués à la même entité, le plus strict s'applique.
Dans cet exemple, le tampon buf
est correctement aligné pour contenir un objet int
, même si son type d'élément est un caractère unsigned char
, ce qui peut nécessiter un alignement plus faible.
alignas(int) unsigned char buf[sizeof(int)];
new (buf) int(42);
alignas
ne peut pas être utilisé pour donner à un type un alignement plus petit que le type sans cette déclaration:
alignas(1) int i; //Il-formed, unless `int` on this platform is aligned to 1 byte.
alignas(char) int j; //Il-formed, unless `int` has the same or smaller alignment than `char`.
alignas
, quand on leur donne une expression constante, doivent recevoir un alignement valide. Les alignements valides sont toujours des puissances de deux et doivent être supérieurs à zéro. Les compilateurs doivent prendre en charge tous les alignements valides jusqu’à l’alignement du type std::max_align_t
. Ils peuvent prendre en charge des alignements plus importants, mais la prise en charge de l'allocation de mémoire pour ces objets est limitée. La limite supérieure des alignements dépend de l'implémentation.
C ++ 17 dispose d'un support direct dans l' operator new
pour allouer de la mémoire aux types sur-alignés.