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 que ce document résout? Quels sont les changements de langue dont je dois être conscient? Et qu'avons-nous launder
?
std::launder
?std::launder
est 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".Réponses:
std::launder
porte bien son nom, mais seulement si vous savez à quoi il sert. Il effectue le blanchiment de la mémoire .Prenons l'exemple du document:
Cette instruction effectue une initialisation agrégée, initialisant le premier membre de
U
with{1}
.Parce qu'il
n
s'agit d'uneconst
variable, le compilateur est libre de supposer qu'ilu.x.n
doit toujours être 1.Alors, que se passe-t-il si nous faisons cela:
Parce que
X
c'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 sonn
membre 2.Alors dis-moi ... qu'est-ce qui
u.x.n
reviendra?La réponse évidente sera 2. Mais c'est faux, car le compilateur est autorisé à supposer qu'une
const
variable vraiment (pas simplement uneconst&
, mais une variable d'objet déclaréeconst
) 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
const
membre est l'un des facteurs de disqualification.Alors ... comment parler
u.x.n
correctement?Nous devons blanchir notre mémoire:
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::launder
peut aussi aider ici:[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.
launder
nous permet de contourner cela.la source
n
c'est uneconst
variable, le compilateur est libre de supposer qu'elleu.x.n
doit 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?ptr
représente, alors vous brisezlaunder
la condition préalable, il est donc inutile de parler du résultat.memcpy
dans une réinterprétation en place sur le laxisme pris en charge (c. -à- alignement) des plates - formes de toute façon .