C ++: ¿Cuál es el tamaño de un objeto de una clase vacía?

Me preguntaba cuál podría ser el tamaño de un objeto de una clase vacía . Seguramente no podría tener 0 bytes, ya que debería ser posible referenciarlo y señalarlo como cualquier otro objeto. Pero, ¿qué tan grande es ese objeto?

Usé este pequeño progtwig:

#include  using namespace std; class Empty {}; int main() { Empty e; cerr << sizeof(e) << endl; return 0; } 

¡El resultado que obtuve en los comstackdores de Visual C ++ y Cygwin-g ++ fue de 1 byte ! Esto fue un poco sorprendente para mí ya que esperaba que fuera del tamaño de la palabra máquina (32 bits o 4 bytes).

¿Alguien puede explicar por qué el tamaño de 1 byte? ¿Por qué no 4 bytes? ¿Esto también depende del comstackdor o de la máquina? Además, ¿alguien puede dar una razón más convincente de por qué un objeto de clase vacío no será de tamaño 0 bytes?

Citando las preguntas frecuentes de estilo y técnica C ++ de Bjarne Stroustrup , la razón por la cual el tamaño no es cero es “para asegurar que las direcciones de dos objetos diferentes serán diferentes”. Y el tamaño puede ser 1 porque la alineación no importa aquí, ya que no hay nada que mirar realmente.

La norma establece que todos los objetos más derivados tienen sizeof ()> = 1:

A menos que sea un campo de bits (bit de clase), el objeto más derivado tendrá un tamaño distinto de cero y ocupará uno o más bytes de almacenamiento. Los sub-objetos de la clase base pueden tener un tamaño cero. ISO / IEC FDIS 14882: 1998 (E) intro.object

Eso es realmente un detalle de implementación. Una vez, hace mucho tiempo, pensé que podría ser cero bytes o mil bytes, que no tiene relación con la especificación del lenguaje. Pero, después de mirar el estándar (sección 5.3.3), sizeof se define como siempre devolviendo uno o más, pase lo que pase.

El tamaño de la clase más derivada debe ser mayor que cero.

Esto es necesario para, entre otras cosas, permitirle manejar arreglos de objetos y punteros a ellos. Si se permitió que sus elementos fueran de tamaño cero, entonces &(array[0]) sería idéntico a &(array[42]) , lo que causará todo tipo de esgulps en sus bucles de procesamiento.

La razón por la cual puede no ser una palabra de máquina es que no hay elementos dentro de ella que realmente requieran que esté alineada en un límite de palabra (como un entero). Por ejemplo, si coloca char x; int y; char x; int y; dentro de la clase, mi GCC lo sincroniza a ocho bytes (ya que el segundo int debe estar alineado en esa implementación).

Aunque no es necesario asignar ninguna memoria para una clase vacía, pero para crear objetos de clases vacías, el comstackdor asigna la memoria mínima que se puede asignar, que es de 1 byte. De esta manera, el comstackdor puede distinguir dos objetos de la misma clase vacía de manera única y podrá asignar la dirección del objeto a un puntero del tipo de clase vacío.

Hay una excepción: matrices de 0 longitud

 #include  class CompletlyEmpty { char NO_DATA[0]; }; int main(int argc, const char** argv) { std::cout << sizeof(CompletlyEmpty) << '\n'; } 

Creo que podría ser útil enlazar con una respuesta que explique esto también. Se trata de boost::compressed_pair por Logan Capaldo .

Esto puede ser útil 🙂 http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a

El tamaño de una clase o estructura vacía es 1

La razón por la que esto sucede se reduce a implementar correctamente el estándar, una de las cosas que el estándar de C ++ dice es que “ningún objeto tendrá la misma dirección en la memoria que cualquier otra variable” …. ¿Cuál es la forma más fácil de asegurar esto? Asegúrese de que todos los tipos tengan un tamaño distinto de cero. Para lograr esto, el comstackdor agrega un byte ficticio a las estructuras y clases que no tienen miembros de datos ni funciones virtuales, de modo que tienen un tamaño de 1 en lugar de un tamaño de 0 y se garantiza que tengan una dirección de memoria única.

La asignación de 1 byte para una clase vacía depende del comstackdor. Los comstackdores deben asegurarse de que los objetos residen en diferentes ubicaciones de memoria y deben asignar un tamaño de memoria distinto de cero a un objeto. Escuche las notas sobre este tema aquí: http://listenvoice.com/listenVoiceNote.aspx?id=27

Aunque los comstackdores asignan un tamaño distinto de cero a una clase vacía, también optimizan cuando las nuevas clases se derivan de clases vacías. Escuche acerca de la optimización de la base vacía en las preguntas de la entrevista de progtwigción c ++ de ListenVoice.

el motivo de la clase sin miembros de datos pero que tiene un tamaño de 1 byte es que este * texto * fuerte debe almacenarse en la memoria para que una referencia o un puntero pueda señalar el objeto de esa clase

clase vacía: esa clase no contiene ningún contenido.

cualquier clase que no esté vacía se representará por su contenido en la memoria.

ahora, ¿cómo se representará la clase vacía en la memoria? como no tiene contenido, no hay manera de mostrar su existencia en la memoria, pero la clase está presente, es obligatorio mostrar su presencia en la memoria. Para mostrar la presencia de clase vacía en la memoria, se requiere 1 byte.

Creo que es así porque como 1 byte es la unidad de memoria más pequeña que se puede usar como marcador de posición, y no puede dar tamaño cero ya que no será posible crear una matriz de objetos.

y lo que dijiste “Esto fue un poco sorprendente para mí, ya que esperaba que fuera del tamaño de la palabra máquina (32 bits o 4 bytes)”. será verdadero para la variable de referencia (palabras de macine) de tipo empty (), no para el tamaño de la clase (que es un tipo de datos abstracto),

Creo que esta pregunta solo tiene interés teórico, pero no importa en la práctica.

Como ya se señaló por otros, derivar de una clase vacía no hace ningún daño, ya que no consumirá ninguna memoria extra para la parte de la clase base.

Además, si una clase está vacía (lo que significa que, teóricamente, no necesita ninguna memoria por instancia, es decir, no tiene ningún miembro de datos no estático ni funciones miembro virtuales), entonces todas sus funciones miembro pueden funcionar igual de bien. (y debería) definirse como estático. Entonces no hay necesidad de crear una instancia de esta clase.

En pocas palabras: si te encuentras escribiendo una clase X vacía, simplemente haz que todas las funciones miembro permanezcan estáticas. Entonces no necesitará crear objetos X, y las clases derivadas no se verán afectadas de ninguna manera.

 #include using namespace std; class Empty { }; int main() { Empty* e1 = new Empty; Empty* e2 = new Empty; if (e1 == e2) cout << "Alas same address of two objects" << endl; else cout << "Okay it's Fine to have different addresses" << endl; return 0; } 

Salida: Está bien, está bien tener diferentes direcciones

La devolución del tamaño 1 garantiza que los dos objetos no tendrán la misma dirección.

No es cero garantizar que los dos objetos diferentes tengan direcciones diferentes. Los diferentes objetos deben tener diferentes direcciones, por lo que el tamaño de una clase vacía es siempre de 1 byte.

Creo que si el tamaño de una clase vacía es cero, significa que no existe. Para que exista (clase), requiere tener al menos 1 byte, ya que este byte es la dirección de memoria / referencia.

Es debido a este puntero, aunque el puntero es (entero) de 4 bytes, pero se refiere a una ubicación de memoria (una unidad) que es de 1 byte.