Pour ce cas de test simplifié:
#include <map>
class Tester {
int foo;
std::map<int, int> smap;
};
int main() {
Tester test;
return 0;
}
J'obtiens l'avertissement du compilateur suivant:
$ clang++ -std=c++98 -Weverything test.cc
test.cc:5:24: warning: padding class 'Tester' with 4 bytes to align 'smap' [-Wpadded]
std::map<int, int> smap;
^
Quelqu'un peut-il expliquer ce que signifie cet avertissement et comment y répondre?
Il n'y a pas vraiment de problème ici. En C et C++, le compilateur est autorisé à insérer un remplissage après les membres de structure pour fournir un meilleur alignement et ainsi permettre un accès plus rapide à la mémoire. Dans ce cas, il semble qu'il ait décidé de placer smap
sur un alignement de 8 octets. Puisqu'un int
fait presque certainement quatre octets, l'avertissement vous indique qu'il y a quatre octets d'espace perdu au milieu de la structure.
S'il y avait plus de membres dans la structure, alors une chose que vous pourriez essayer serait de changer l'ordre des définitions. Par exemple, si votre Tester
avait des membres:
struct Tester {
int foo;
std::map<int, int> smap;
int bar;
};
il serait alors judicieux de placer les deux pouces l'un à côté de l'autre pour optimiser l'alignement et éviter le gaspillage d'espace. Cependant, dans ce cas, vous n'avez que deux membres, et si vous les changez, le compilateur ajoutera probablement encore quatre octets de remplissage à la fin de la structure afin d'optimiser l'alignement de Tester
s une fois placé à l'intérieur d'un tableau.
Je suppose que vous compilez cela sur un système 64 bits.
Sur les systèmes 64 bits, les pointeurs font 8 octets. Les compilateurs aligneront les membres de la structure sur les limites naturelles, donc un pointeur de 8 octets commencera à un décalage dans une structure qui est un multiple de 8 octets.
Puisque int
n'est que de quatre octets, le compilateur a inséré 4 octets de "padding" après foo
, de sorte que smap
se trouve sur une limite de 8 octets.
Edit: Alors que smap
n'est pas un pointeur, mais un std::map
, la même logique s'applique. Je ne sais pas quelles sont les règles exactes d'alignement des objets, mais la même chose se produit.
Que faire? Rien. Votre code est parfaitement correct, le compilateur vous fait juste savoir que cela s'est produit. Il n'y a absolument rien à craindre. -Weverything
signifie activer tous les avertissements possibles , ce qui est probablement excessif pour la plupart des compilations.
Votre compilateur sur votre système a choisi de donner des pointeurs sur votre système 64 bits 8 bytes
, int dans la structure a 4 bytes
. Des problèmes/avertissements similaires se produisent beaucoup ces jours-ci en travaillant avec des exemples de code plus anciens, j'ai donc dû creuser plus profondément.
Pour faire court, int
a été défini dans les années 60 sans système 64 bits, sans gigaoctets de stockage ni Go de RAM à l'esprit.
Pour résoudre votre message d'erreur, utilisez size_t
(type de taille) au lieu de int
si nécessaire - dans votre cas avec le map stl car il est programmé pour fonctionner sur plusieurs systèmes différents.
Avec size_t
votre compilateur peut choisir lui-même la taille en octets dont il a besoin s'il compile sur un système 32 bits ou un système ou bit 64 bits ou quoi que ce soit et le message est parti et vous n'aurez même pas à modifier votre code, quel que soit le système vous pouvez compiler votre code pour à l'avenir.