c++ - memoria - punteros a cadenas
¿Cómo se almacenan los objetos en la memoria en C++? (5)
Casi. Lanzaste a un Object * y no tomaste una dirección. Vamos a volver a preguntar como el siguiente:
((int*)&myObject)[0] == i1
Tienes que ser muy cuidadoso con suposiciones como esta. Como ha definido la estructura, esto debería ser cierto en cualquier compilador con el que se encuentre. Pero todo tipo de otras propiedades del objeto (que puede haber omitido en su ejemplo), como otros dijeron, lo convierten en no POD y podría (posiblemente de una manera dependiente del compilador) hacer que la declaración anterior no sea verdadera.
Tenga en cuenta que no me apresuraría a decirle que funcionaría si hubiera preguntado acerca de i3, en ese caso, incluso para POD simple, la alineación o la endianidad podrían arruinarlo fácilmente.
En cualquier caso, deberías evitar este tipo de cosas, si es posible. Incluso si funciona bien ahora, si usted (o cualquier otra persona que no comprenda que está haciendo este truco) alguna vez cambia el orden de la estructura o agrega nuevos campos, este truco fallará en todos los lugares donde lo haya usado, que puede ser difícil de encontrar
Responda su edición: si esa es su definición de clase completa, y está utilizando uno de los compiladores convencionales con opciones predeterminadas, y ejecutándose en un procesador x86, entonces sí, probablemente haya adivinado el diseño de memoria correcto. Pero la elección del compilador, las opciones del compilador y la arquitectura de CPU diferente podrían invalidar fácilmente sus suposiciones.
¿Cómo se almacenan los objetos en la memoria en C ++?
Para una clase regular como
class Object
{
public:
int i1;
int i2;
char i3;
int i4;
private:
};
¿Usar un puntero de Object como una matriz puede usarse para acceder a i1 de la siguiente manera?
((Object*)&myObject)[0] === i1?
Otras preguntas sobre SO parecen sugerir que lanzar una estructura a un puntero apunta al primer miembro para POD-types. ¿Cómo es esto diferente para las clases con constructores, en todo caso? ¿De qué manera es diferente para los tipos que no son POD?
Editar:
En la memoria, ¿la clase anterior sería distribuida de la siguiente manera?
[i1 - 4bytes][i2 - 4bytes][i3 - 1byte][padding - 3bytes][i4 - 4bytes]
La diferencia es que este truco solo es válido para los tipos de POD. Eso es todo lo que hay que hacer. El estándar especifica que este molde es válido para un tipo de POD, pero no garantiza lo que sucede con los tipos que no son POD.
Por lo general, lo que importa no es si la clase tiene un constructor: lo que importa es si la clase tiene algún método virtual. Para más detalles, google para ''vtable'' y ''vptr''.
Las clases sin miembros virtuales y sin herencia se presentan en la memoria al igual que las estructuras. Pero, cuando comienzas a obtener niveles de herencia, las cosas pueden ser complicadas y puede ser difícil adivinar en qué orden están las cosas en la memoria (particularmente la herencia múltiple).
Cuando tiene miembros virtuales, tienen un "vtable" en la memoria que contiene punteros a la función real que se crea en función de la jerarquía de herencia de la clase.
El resultado final es: no accedas a las clases de esta manera en absoluto si puedes evitarlo (y tampoco las resuelves o las agregas). Si debe hacer esto (¿por qué?), Tenga cuidado de saber exactamente cómo van a quedar sus objetos de clase en la memoria y tenga cuidado de evitar la herencia.
Realmente depende del compilador, o más bien, queda en manos del compilador determinar el diseño de la memoria.
Por ejemplo, una combinación de variables de miembros públicas, privadas y protegidas podría establecerse de modo que cada tipo de acceso sea contiguo. O bien, las clases derivadas podrían tener variables miembro intercaladas con espacio no utilizado en la superclase.
Las cosas empeoran con la herencia virtual, donde las clases base virtualmente heredadas pueden distribuirse en cualquier lugar de la memoria asignada para esa instancia en particular.
POD es diferente porque necesita ser compatible con C.