Quel est le but de std :: launder?

242

P0137 introduit le modèle de fonction std::launderet 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 que ce document résout? Quels sont les changements de langue dont je dois être conscient? Et qu'avons-nous launder?

Barry
la source
2
Vous posez des questions sur le papier lui-même ou sur std::launder? std::launderest utilisé pour "obtenir un pointeur vers un objet créé dans le stockage occupé par un objet existant du même type, même s'il a des membres const ou reference".
txtechhelp
7
lien utile sur le sujet. Aussi cette question stackoverflow.com/questions/27003727/…
Paul Rooney
Cela a maintenant été publié dans VC2017 dans la version 15.7.0
Damian
Selon le std, les pointeurs sont des types triviaux, donc le blanchiment ne fait rien. ;)
curiousguy

Réponses:

250

std::launderporte bien son nom, mais seulement si vous savez à quoi il sert. Il effectue le blanchiment de la mémoire .

Prenons l'exemple du document:

struct X { const int n; };
union U { X x; float f; };
...

U u = {{ 1 }};

Cette instruction effectue une initialisation agrégée, initialisant le premier membre de Uwith {1}.

Parce qu'il ns'agit d'une constvariable, le compilateur est libre de supposer qu'il u.x.ndoit toujours être 1.

Alors, que se passe-t-il si nous faisons cela:

X *p = new (&u.x) X {2};

Parce que Xc'est trivial, nous n'avons pas besoin de détruire l'ancien objet avant d'en créer un nouveau à sa place, c'est donc un code parfaitement légal. Le nouvel objet aura son nmembre 2.

Alors dis-moi ... qu'est-ce qui u.x.nreviendra?

La réponse évidente sera 2. Mais c'est faux, car le compilateur est autorisé à supposer qu'une constvariable vraiment (pas simplement une const&, mais une variable d'objet déclarée const ) ne changera jamais . Mais nous venons de le changer.

[basic.life] / 8 décrit les circonstances dans lesquelles il est OK d'accéder à l'objet nouvellement créé via des variables / pointeurs / références à l'ancien. Et avoir un constmembre est l'un des facteurs de disqualification.

Alors ... comment parler u.x.ncorrectement?

Nous devons blanchir 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 retrouver d'où vous avez tiré votre argent. Le blanchiment de la mémoire est utilisé pour empêcher le compilateur de retrouver d'où vous venez votre objet, le forçant ainsi à éviter toute optimisation qui pourrait ne plus s'appliquer.

Un autre des facteurs disqualifiants est si vous changez le type de l'objet. std::launderpeut aussi aider ici:

aligned_storage<sizeof(int), alignof(int)>::type data;
new(&data) int;
int *p = std::launder(reinterpret_cast<int*>(&data));

[basic.life] / 8 nous dit que, si vous allouez un nouvel objet dans le stockage de l'ancien, vous ne pouvez pas accéder au nouvel objet via des pointeurs vers l'ancien. laundernous permet de contourner cela.

Nicol Bolas
la source
34
Mon tl; dr a-t-il donc raison: "le blanchiment est essentiellement un type de punning de type non UB"?
druckermanly
13
Pourriez-vous expliquer pourquoi cela est vrai? "Parce que nc'est une constvariable, le compilateur est libre de supposer qu'elle u.x.ndoit toujours être 1." Où dans la norme cela dit-il cela? Je pose la question parce que le problème même que vous avez signalé me ​​semble impliquer qu'il est faux en premier lieu. Cela ne devrait être vrai qu'en vertu de la règle «comme si», qui échoue ici. Qu'est-ce que je rate?
user541686
10
@Mehrdad [basic.life] / 8: " Si, un [...] nouvel objet est créé à l'emplacement de stockage que l'objet d'origine occupait [...] le nom de l'objet d'origine fera automatiquement référence au nouvel objet [...] si: [...] le type [...] ne contient aucun membre de données non statique dont le type est qualifié const ou un type de référence [...] "
ecatmur
14
@Barry Very; s'il n'y a pas d'objets de type T situés à l'adresse que ptrreprésente, alors vous brisez launderla condition préalable, il est donc inutile de parler du résultat.
TC
17
@NicolBolas On ne peut qu'espérer que supercat fait autant de lobbying auprès des Comités qu'ils exigent sans cesse des réponses de la part d'autres utilisateurs de langues tierces sur SO. En outre, un bon compilateur optimisé permettra d' optimiser votre solution correcte memcpydans une réinterprétation en place sur le laxisme pris en charge (c. -à- alignement) des plates - formes de toute façon .
underscore_d