std::launder
porte bien son nom, mais seulement si vous savez ce que c'est. Il effectue la mémoire de blanchiment d'argent.
Prenez, par exemple, dans le document:
struct X { const int n; };
union U { X x; float f; };
...
U u = {{ 1 }};
Cette instruction effectue globale de l'initialisation, l'initialisation du premier membre de l' U
avec {1}
.
Parce qu' n
est const
variable, le compilateur est libre de supposer qu' u.x.n
doit toujours être 1.
Donc, ce qui se produit si nous faisons cela:
X *p = new (&u.x) X {2};
Parce qu' X
est trivial, nous n'avons pas besoin de détruire l'ancien objet avant d'en créer un nouveau à sa place, donc c'est parfaitement légal de code. Le nouvel objet aura sa n
de ses membres 2.
Alors, dites-moi... que vais - u.x.n
de retour?
La réponse la plus évidente sera de 2. Mais c'est faux, parce que le compilateur est permis de supposer que, véritablement const
variable (pas simplement un const&
, mais un objet variable déclarée const
) ne changeront jamais. Mais nous avons juste changé.
[de base.la vie]/8 énonce les circonstances dans lesquelles il est OK pour accéder à l'objet nouvellement créé par des variables/pointeurs/références à l'ancien. Et avoir un const
membre est l'un des facteurs de disqualification.
Donc... comment peut-on parler d' u.x.n
correctement?
Nous devons nous laver de notre mémoire:
assert(*std::launder(&u.x.n) == 2); //Will be true.
Le blanchiment d'argent est utilisé pour empêcher les gens de traçage de l'endroit où vous avez obtenu votre argent. Mémoire de blanchiment d'argent est utilisé pour empêcher le compilateur de traçage de l'endroit où vous avez obtenu votre objet, ainsi forcer pour éviter toute optimisations qui peuvent ne plus s'appliquer.
Un autre des facteurs de disqualification est si vous modifiez le type de l'objet. std::launder
peut aider à ici aussi:
aligned_storage<sizeof(int), alignof(int)>::type data;
new(&data) int;
int *p = std::launder(reinterpret_cast<int*>(&data));
[de base.la vie]/8 nous dit que, si vous alloue un nouvel objet dans le stockage de l'ancien, vous ne pouvez pas accéder à la nouvelle de l'objet par le biais de pointeurs à l'ancienne. launder
nous permet de côté-étape.