P0137 apresenta o modelo de função std::launder
e faz muitas e muitas alterações no padrão nas seções relativas a uniões, vida útil e ponteiros.
Qual é o problema que este artigo está resolvendo? Quais são as alterações no idioma que eu tenho que estar ciente? E o que estamos launder
ing?
std::launder
?std::launder
é usado para "obter um ponteiro para um objeto criado no armazenamento ocupado por um objeto existente do mesmo tipo, mesmo que possua membros const ou de referência".Respostas:
std::launder
é apropriadamente nomeado, embora apenas se você souber para que serve. Ele executa lavagem de memória .Considere o exemplo no artigo:
Essa instrução executa inicialização agregada, inicializando o primeiro membro de
U
with{1}
.Por
n
ser umaconst
variável, o compilador pode assumir que sempreu.x.n
deve ser 1.Então, o que acontece se fizermos isso:
Por
X
ser trivial, não precisamos destruir o objeto antigo antes de criar um novo em seu lugar, portanto esse é um código perfeitamente legal. O novo objeto terá seun
membro como 2.Então me diga ... o que
u.x.n
retornará?A resposta óbvia será 2. Mas isso está errado, porque o compilador pode assumir que uma
const
variável verdadeiramente (não apenas umaconst&
, mas uma variável de objeto declaradaconst
) nunca será alterada . Mas nós apenas mudamos.[basic.life] / 8 explica as circunstâncias em que não há problema em acessar o objeto recém-criado através de variáveis / ponteiros / referências ao antigo. E ter um
const
membro é um dos fatores desqualificantes.Então ... como podemos falar
u.x.n
corretamente?Temos que lavar nossa memória:
A lavagem de dinheiro é usada para impedir que as pessoas rastreiem de onde você conseguiu seu dinheiro. A lavagem de memória é usada para impedir que o compilador rastreie onde você obteve seu objeto, forçando-o a evitar otimizações que podem não se aplicar mais.
Outro dos fatores desqualificantes é se você alterar o tipo do objeto.
std::launder
também pode ajudar aqui:[basic.life] / 8 nos diz que, se você alocar um novo objeto no armazenamento do antigo, não poderá acessar o novo objeto por meio de ponteiros para o antigo.
launder
nos permite dar um passo adiante.fonte
n
é umaconst
variável, o compilador é livre para assumir queu.x.n
sempre será 1." Onde no padrão diz isso? Eu pergunto porque o próprio problema que você apontou parece implicar para mim que é falso em primeiro lugar. Só deve ser verdade sob a regra como se, que falha aqui. o que estou perdendo?ptr
, então você quebrarálaunder
a pré-condição, portanto não faz sentido falar sobre o resultado.memcpy
para uma reinterpretação no local em plataformas suportadas (isto é, alinhamento laxista) de qualquer maneira .