En C++, la mayoría de las optimizaciones se derivan de la regla de si. Es decir, siempre que el programa se comporte como si no hubiera tenido lugar una optimización, entonces son válidos.Optimización de miembros de datos vacíos: ¿sería posible?
La optimización de base vacía es uno de estos trucos: en algunas condiciones, si la clase base está vacía (no tiene ningún miembro de datos no estáticos), el compilador puede eludir su representación de memoria.
Aparentemente parece que la norma prohíbe esta optimización de los miembros de datos, es decir, incluso si un miembro de datos está vacía, todavía debe tomar por lo menos un valor de byte del lugar: desde N3225, [clase]
4 - Los objetos completos y los subobjetos miembros de clase tienen un tamaño distinto de cero.
Nota: esto conduce a la utilización de la herencia privada para el diseño de políticas con el fin de tener EBO entran en juego cuando sea apropiado
Me preguntaba si, utilizando el como-si la regla, se podría seguir siendo capaz de realizar esta optimización
edición: tras una serie de respuestas y comentarios, y para hacerlo más claro lo que estoy preguntando acerca.
En primer lugar, te voy a dar un ejemplo:
struct Empty {};
struct Foo { Empty e; int i; };
Mi pregunta es, ¿por qué es sizeof(Foo) != sizeof(int)
? En particular, a menos que especifique algún empaque, es probable que debido a problemas de alineación, Foo tenga el doble del tamaño de int, lo que parece ridículamente inflado.
Nota: mi pregunta no es por qué es sizeof(Foo) != 0
, esto no es realmente necesario, ya sea por EBO
Según C++, es porque no tiene ningún problema-objeto puede tener un tamaño cero. Sin embargo, una base está autorizada a tener un tamaño cero (EBO), por lo tanto:
struct Bar: Empty { int i; };
es probable que (gracias a EBO) a obedecer sizeof(Bar) == sizeof(int)
.
Steve Jessop parece ser una opinión de que no hay dos subobjetos que tengan la misma dirección. Pensaba en ello, sin embargo, no impide en realidad la optimización en la mayoría de los casos:
Si tiene memoria "sin usar", entonces es trivial:
struct UnusedPadding { Empty e; Empty f; double d; int i; };
// chances are that the layout will leave some memory after int
Pero, de hecho, es incluso "peor "que eso, porque el espacio Empty
nunca se escribe (será mejor que no lo haga si EBO entra en acción ...) Y, por tanto, en realidad se podría colocarlo en un lugar ocupado que no es la dirección de otro objeto:
struct Virtual { virtual ~Virtual() {} Empty e; Empty f; int i; };
// most compilers will reserve some space for a virtual pointer!
O, incluso en nuestro caso original:
struct Foo { Empty e; int i; }; // deja vu!
Uno podría tener (char*)foo.e == (char*)foo.i + 1
si todo lo que quería una dirección diferente.
Eche un vistazo a la biblioteca de Boost [Compressed Pair] (http://www.boost.org/doc/libs/1_45_0/libs/utility/compressed_pair.htm) para ver cómo obtener esta optimización. – GManNickG
@GMan: hábilmente usan EBO. Pero en realidad este uso de EBO es exactamente lo que me impulsó a comenzar mi pregunta. –
Vea esto: [Cuando los programadores usan la Optimización de Base Vacía (EBO)] (http://stackoverflow.com/questions/4325144/scenario-when-do-programmers-use-empty-base-optimization-ebo) – Nawaz