Les règles entourant l'aliasing strict peuvent être assez délicates.
Voici un exemple d'aliasing strict :
int a = 0;
float* f = reinterpret_cast<float*>(&a);
f = 0.3;
printf("%d", a);
C'est une violation stricte de l'aliasing car :
- la durée de vie des variables (et leur utilisation) se chevauche
- ils interprètent le même morceau de mémoire à travers deux "lentilles" différentes.
Si vous ne faites pas les deux en même temps, alors votre code ne viole pas l'aliasing strict.
En C++, la durée de vie d'un objet commence à la fin du constructeur et s'arrête au début du destructeur.
Dans le cas des types intégrés (pas de destructeur) ou des PODs (destructeur trivial), la règle est plutôt que leur durée de vie se termine lorsque la mémoire est soit écrasée, soit libérée.
Note : ceci est spécifiquement destiné à supporter l'écriture des gestionnaires de mémoire ; après tout malloc
est écrit en C et operator new
est écrit en C++ et ils sont explicitement autorisés à mettre la mémoire en commun.
J'ai utilisé spécifiquement objectifs au lieu de types car la règle est un peu plus difficile.
Le C++ utilise généralement saisie nominale : si deux types ont un nom différent, ils sont différents. Si vous accédez à une valeur de type dynamique T
comme s'il s'agissait d'un U
alors vous violez l'aliasing.
Il existe un certain nombre d'exceptions à cette règle :
- accès par la classe de base
- dans les PODs, accès en tant que pointeur vers le premier attribut
Et la règle la plus compliquée est liée à union
où le C++ passe à typage structurel : vous pouvez accéder à un morceau de mémoire par deux types différents, si vous n'accédez qu'aux parties du début de ce morceau de mémoire dans lesquelles les deux types partagent une séquence initiale commune.
§9.2/18 Si une union standard-layout contient deux ou plusieurs structures standard-layout qui partagent une séquence initiale commune, et si l'objet union standard-layout contient actuellement une de ces structures standard-layout, il est permis d'inspecter la partie initiale commune de n'importe laquelle d'entre elles. Deux structs standard-layout partagent une séquence initiale commune si les membres correspondants ont des types compatibles avec la mise en page et si aucun des membres n'est un champ de bits ou si les deux sont des champs de bits avec la même largeur pour une séquence d'un ou plusieurs membres initiaux.
Étant donné :
struct A { int a; };
struct B: A { char c; double d; };
struct C { int a; char c; char* z; };
Dans un délai de union X { B b; C c; };
vous pouvez accéder x.b.a
, x.b.c
et x.c.a
, x.c.c
en même temps ; toutefois, l'accès x.b.d
(respectivement x.c.z
) est une violation de l'aliasing si le type actuellement stocké n'est pas B
(respectivement pas C
).
Remarque : de manière informelle, le typage structurel revient à ramener le type à un tuple de ses champs (en les aplatissant).
Note : char*
est spécifiquement exemptée de cette règle, vous pouvez visualiser n'importe quel morceau de mémoire à travers char*
.
Dans votre cas, sans la définition de Data
Je ne peux pas dire si la règle des "lentilles" pourrait être violée, cependant puisque vous le faites :
- en écrasant la mémoire avec
Data
avant d'y accéder par le biais de Data*
- ne pas y accéder par
int*
ensuite
alors vous êtes en conformité avec la règle de la durée de vie, et donc il n'y a pas d'aliasing en ce qui concerne le langage.