ein apoya la huelga de moderadores
Acabo de leer
¿Cuál es el propósito de std::launder?
y francamente, me quedo rascándome la cabeza.
Comencemos con el segundo ejemplo en la respuesta aceptada de @NicolBolas:
aligned_storage<sizeof(int), alignof(int)>::type data; new(&data) int; int *p = std::launder(reinterpret_cast<int*>(&data));
[basic.life]/8 nos dice que, si asigna un nuevo objeto en el almacenamiento del antiguo, no puede acceder al nuevo objeto a través de punteros al antiguo.
std::launder
nos permite esquivar eso.
Entonces, ¿por qué no simplemente cambiar el estándar de idioma para que acceder data
a través de un reinterpret_cast<int*>(&data)
es válido/apropiado? En la vida real, el lavado de dinero es una forma de ocultar la realidad a la ley. Pero no tenemos nada que ocultar, aquí estamos haciendo algo perfectamente legítimo. Entonces, ¿por qué el compilador no puede simplemente cambiar su comportamiento a su std::launder()
comportamiento cuando nota que estamos accediendo data
¿Por aquí?
En el primer ejemplo:
X *p = new (&u.x) X {2};
Debido a que X es trivial, no necesitamos destruir el objeto anterior antes de crear uno nuevo en su lugar, por lo que este es un código perfectamente legal. El nuevo objeto tendrá su miembro n 2.
Así que dime… ¿qué será
u.x.n
¿devolver?La respuesta obvia será 2. Pero eso es incorrecto, porque el compilador puede asumir que un verdadero
const
variable (no simplemente una const&, sino una variable de objeto declaradaconst
) nunca cambiará. Pero lo acabamos de cambiar.
Entonces, ¿por qué no hacer que el compilador no ¿Se permitirá hacer la suposición cuando escribimos este tipo de código, accediendo al campo constante a través del puntero?
¿Por qué es razonable tener esta pseudofunción para hacer un agujero en la semántica del lenguaje formal, en lugar de establecer la semántica como debe ser dependiendo de si el código hace o no algo como en estos ejemplos?
Nicolás Bolas
dependiendo de si el código hace o no algo como en estos ejemplos
Debido a que el compilador no siempre puede saber cuándo data
se está accediendo “de esta manera”.
Tal como están las cosas actualmente, el compilador puede asumir que, para el siguiente código:
struct foo{ int const x; };
void some_func(foo*);
int bar() {
foo f { 123 };
some_func(&f);
return f.x;
}
bar
siempre devolverá 123. El compilador puede generar código que realmente acceda al objeto. Pero el modelo de objetos no requerir este. f.x
es un const
objeto (no una referencia/puntero a const
), y por lo tanto no se puede cambiar. Y f
se requiere nombrar siempre el mismo objeto (de hecho, estas son las partes del estándar que tendría que cambiar). Por lo tanto, el valor de f.x
no se puede cambiar por ningún medio que no sea UB.
¿Por qué es razonable tener esta pseudofunción para abrir un agujero en la semántica del lenguaje formal?
Esto era realmente discutido. Ese documento menciona cuánto tiempo han existido estos problemas (es decir, desde C++ 03) y, a menudo, se han empleado las optimizaciones posibles gracias a este modelo de objetos.
La propuesta fue rechazada con el argumento de que en realidad no solucionaría el problema. De este informe de viaje:
Sin embargo, durante la discusión salió a la luz que la alternativa propuesta no manejaría todos los escenarios afectados (particularmente los escenarios donde los punteros de vtable están en juego), y no obtuvo consenso.
El informe no entra en ningún detalle en particular sobre el asunto, y las discusiones en cuestión no están disponibles públicamente. Pero la propia propuesta sí señala que no permitiría desvirtualizar un segundo llamada de función virtual, ya que la primera llamada puede haber creado un nuevo objeto. Entonces, incluso P0532 no haría launder
innecesario, simplemente menos necesario.
-
Pero, ¿y si por dentro
some_func()
Yo sueloconst_cast
sobre elx
¿campo?– ein apoya la huelga de moderadores
12 de febrero de 2021 a las 20:27
-
re. su segundo comentario, los compiladores que carecen de una optimización no son motivos para sospechar del estándar. Otras razones para las optimizaciones perdidas incluyen: nadie se puso a trabajar para agregar este caso al optimizador; y la base de usuarios que espera un comportamiento no estándar. Caso similar sin la estructura se optimiza; estructuras con
const
los miembros son poco comunes–MM
12 de febrero de 2021 a las 21:19
-
@einpoklum modificando
f.x
durante la vida dex
(a través deconst_cast
) es UB por [dcl.type.cv]/4. Poner fin a la vida dex
y/of
dentrosome_func
se permitiría por sí solo, pero eso causaría el acceso posterior secuenciado enbar
ser UB por [basic.life]/(8.3).– Aschepler
12 de febrero de 2021 a las 21:20
-
Me parece bien. Pero dada esta situación, yo diría
std::launder
es lo contrario de aptly-named.std::soil
sería mucho más apropiado.– ein apoya la huelga de moderadores
12 de febrero de 2021 a las 22:50
-
Creo que el ejemplo de “subobjeto const” ya no es relevante: github.com/cplusplus/draft/commit/…
– mojar
15 de febrero de 2021 a las 8:46
supongo que
launder
optimizaciones deshabilitadas, en un alcance muy pequeño.– mojar
12 de febrero de 2021 a las 18:08
“Entonces, ¿por qué no hacer que el compilador no pueda hacer suposiciones cuando escribimos este tipo de código?“¿Quieres decir, además del hecho obvio de que el compilador tendría que generar código subóptimo el 99% del tiempo? La mayoría de la gente no andar recreando objetos almacenados, así que asumiendo que
u.x.n
no cambia es completamente razonable.– Nicolás Bolas
12 de febrero de 2021 a las 18:17
@dyp: ¿Adivina qué? Tiene que asumir que ya.
– ein apoya la huelga de moderadores
12 de febrero de 2021 a las 19:25
@einpoklum: “Tiene que asumir eso ya.” Estás confundiendo el código compilado con el estándar requiere suceder No hay nada en el estándar que requiera explícitamente que los compiladores asuman algo por el estilo.
– Nicolás Bolas
12 de febrero de 2021 a las 19:38
@NicolBolas: ¿Está diciendo que ese ejemplo es solo una optimización perdida? Tenía la impresión de que un
const
El calificador en un valor para una función no es una garantía para el compilador, sino una precaución de seguridad para permitir que el compilador evite que usted, el autor, lo cambie.– ein apoya la huelga de moderadores
12 de febrero de 2021 a las 19:55