¿Perdura el efecto de std::launder después de la expresión en la que se llama?
Considere el siguiente código de muestra:
struct X { const int n; };
union U { X x; float f; };
void fun() {
U u = {{ 1 }};
u.f = 5.f; // OK, crea un nuevo subobjeto de 'u'
X *p = new (&u.x) X {2}; // OK, crea un nuevo subobjeto de 'u'
}
if(*std::launder(&u.x.n) == 2){// la condición es verdadera debido a std::launder
std::cout << u.x.n << std::endl; // ¿UB aquí?
}
¿Qué imprime la función fun
según el estándar del lenguaje? En otras palabras, ¿el efecto de std::launder
dura más allá de la expresión en la que se llama? ¿O tenemos que usar std::launder
cada vez que necesitamos acceder al valor actualizado de u.x.n
?
davy.ai
El comportamiento del código es indefinido. Si bien el uso de
std::launder
parece proporcionar una forma de acceder al valor actualizado deu.x.n
, no garantiza que el valor pueda ser accedido de manera segura posteriormente. El efecto destd::launder
solo dura para la expresión en la que se llama, y el estándar establece que “cuando finaliza la vida útil de un objeto y se reutiliza o libera su almacenamiento, cualquier puntero, referencia o iterador que haga referencia al objeto es indeterminado o tiene una validez limitada”. Por lo tanto, acceder al valor deu.x.n
después de que haya finalizado su vida útil, como es el caso en la instrucción condicional, da como resultado un comportamiento indefinido.