[Ne pas dupliquer Rembourrage et emballage de la structure . Cette question porte sur la manière et le moment où le rembourrage se produit. Celle-ci porte sur la manière de le gérer].
Je viens de réaliser combien de mémoire est gaspillée à cause de l'alignement en C++. Considérons l'exemple simple suivant :
struct X
{
int a;
double b;
int c;
};
int main()
{
cout << "sizeof(int) = " << sizeof(int) << '\n';
cout << "sizeof(double) = " << sizeof(double) << '\n';
cout << "2 * sizeof(int) + sizeof(double) = " << 2 * sizeof(int) + sizeof(double) << '\n';
cout << "but sizeof(X) = " << sizeof(X) << '\n';
}
En utilisant g++, le programme donne la sortie suivante :
sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 24
Cela représente une surcharge de mémoire de 50 % ! Dans une matrice de 3 gigaoctets de 134'217'728 X
d'un gigaoctet serait du pur rembourrage.
Heureusement, la solution au problème est très simple - il suffit d'échanger double b
y int c
autour :
struct X
{
int a;
int c;
double b;
};
Maintenant, le résultat est beaucoup plus satisfaisant :
sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 16
Il y a cependant un problème : ce n'est pas cross-compatible. Oui, sous g++ un int
est de 4 octets et un double
est de 8 octets, mais ce n'est pas nécessairement toujours vrai (leur alignement ne doit pas être le même non plus), donc dans un environnement différent, cette "correction" pourrait non seulement être inutile, mais elle pourrait aussi potentiellement aggraver les choses en augmentant la quantité de remplissage nécessaire.
Existe-t-il un moyen fiable et multiplateforme de résoudre ce problème ? (minimiser la quantité de rembourrage nécessaire sans souffrir d'une baisse de performance due à un mauvais alignement ) ? Pourquoi le compilateur n'effectue-t-il pas ces optimisations ? (échanger les membres de la structure/classe pour réduire le rembourrage) ?
Clarification
En raison d'un malentendu et d'une confusion, je tiens à souligner que Je ne veux pas "emballer" mon struct
. C'est-à-dire que je ne veux pas que ses membres soient non alignés et donc plus lents à accéder. Au lieu de cela, je veux toujours que tous les membres soient auto-alignés, mais d'une manière qui utilise le moins de mémoire possible sur le padding. Ce problème peut être résolu en utilisant, par exemple, un réarrangement manuel tel que décrit ici et dans le document L'art perdu de faire ses bagages par Eric Raymond. Je suis à la recherche d'un moyen automatisé et aussi multiplateforme que possible de faire cela, similaire à ce qui est décrit dans le document suivant proposition P1112 pour la future norme C++20.