c++ - ¿Es posible obtener un puntero a un subobjeto a través de un puntero a un subobjeto diferente y no publicado?
pointers language-lawyer (1)
Esto está perfectamente bien definido:
void something(int *x) {
reinterpret_cast<Point*>(x)->y = 42;
}
El objeto
Point
(
p
) y su miembro
x
son interconvertibles por puntero, de
[basic.compound]
:
Dos objetos ayb son interconvertibles por puntero si:
- [...]
- uno es un objeto de clase de diseño estándar y el otro es el primer miembro de datos no estáticos de ese objeto o, si el objeto no tiene miembros de datos no estáticos, cualquier subobjeto de clase base de ese objeto ([class.mem]) o:
- [...]
Si dos objetos son interconvertibles por puntero, tienen la misma dirección y es posible obtener un puntero a uno de un puntero a otro a través de un
reinterpret_cast
.
Ese
reinterpret_cast<Point*>(x)
es válido y termina con un puntero que apunta a
p
.
Por lo tanto, modificarlo directamente está bien.
Como puede ver, la parte de diseño estándar y la primera parte del miembro de datos no estáticos son significativas.
Aunque no es como si los compiladores en cuestión optimizaran la carga adicional si pasa un puntero a
py
y devuelve
px
lugar.
Mira este código simple:
struct Point {
int x;
int y;
};
void something(int *);
int main() {
Point p{1, 2};
something(&p.x);
return p.y;
}
Espero que el valor de retorno de ese
main
se pueda optimizar para
return 2;
, como
something
no tiene acceso a
py
, solo obtiene un puntero a
px
.
Pero ninguno de los principales compiladores optimiza el valor de retorno de
main
a
2
.
Godbolt
¿Hay algo en el estándar que permita que
something
modifique
py
si solo damos acceso a
px
?
En caso afirmativo, ¿depende esto de si
Point
tiene un diseño estándar?
¿Qué pasa si uso
something(&p.y);
, y
return px;
¿en lugar?