315 votes

Quel est le but de std :: launder?

P0137 introduit le modèle de fonction std::launder et apporte de nombreuses modifications à la norme dans les sections concernant les unions, la durée de vie et les pointeurs.

Quel est le problème résolu par ce document? Quels sont les changements de langue que je dois connaître? Et que sommes-nous launder ing?

322voto

Nicol Bolas Points 133791

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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X