c++ - nyquist - ¿Esto realmente rompe las reglas de aliasing estricto?
efecto aliasing pdf (2)
La advertencia está absolutamente justificada. El puntero decaído a los data
no apunta a un objeto de tipo int
, y su conversión no cambia eso. Ver [basic.life]/7 :
Si, una vez que finaliza la vida útil de un objeto y antes de que se reutilice o libere el almacenamiento que ocupó el objeto ocupado, se creará un nuevo objeto en la ubicación de almacenamiento que ocupaba el objeto original, un puntero que apuntaba al objeto original , una referencia que referido al objeto original, o el nombre del objeto original se referirá automáticamente al nuevo objeto y, una vez que ha comenzado la vida útil del nuevo objeto, puede usarse para manipular el nuevo objeto si :
(7.1) - [..]
(7.2) - el nuevo objeto es del mismo tipo que el objeto original (ignorando los calificadores cv de nivel superior) ,
El nuevo objeto no es una matriz de caracteres, sino un int
. P0137 , que formaliza la noción de apuntar, agrega el launder
:
[ Nota : Si no se cumplen estas condiciones, se puede obtener un puntero al nuevo objeto a partir de un puntero que representa la dirección de su almacenamiento llamando a
std::launder
(18.6 [support.dynamic]). - nota final ]
Es decir, su fragmento se puede corregir de esta manera:
std::cout << *std::launder(reinterpret_cast<int*>(data));
... o simplemente inicialice un nuevo puntero del resultado de la ubicación nueva, que también elimina la advertencia.
Cuando compilo este código de ejemplo usando g ++, recibo esta advertencia:
advertencia: la desreferenciación del puntero con tipo de letra infringirá las reglas de alias estricto
[-Wstrict-aliasing]
El código:
#include <iostream>
int main()
{
alignas(int) char data[sizeof(int)];
int *myInt = new (data) int;
*myInt = 34;
std::cout << *reinterpret_cast<int*>(data);
}
En este caso, ¿ data
alias de data
no es un int y, por lo tanto, devolverlo a un int no violaría las reglas estrictas de alias? ¿O me estoy perdiendo algo aquí?
Edición: Extraño, cuando defino data
como este:
alignas(int) char* data = new char[sizeof(int)];
La advertencia del compilador desaparece. ¿La asignación de pila marca la diferencia con un alias estricto? ¿El hecho de que sea un char[]
y no un char*
significa que no puede ser alias de ningún tipo?
Que hay de cambiar
std::cout << *reinterpret_cast<int*>(data);
a
int *tmp = reinterpret_cast<int*>(data);
std::cout << *tmp;
?
En mi caso se libró de la advertencia.