2010-07-30 9 views
8

Digamos que tenemos una clase que tiene este aspecto:Estructura de la memoria de un objeto que solo funciona?

class A 
{ 
    public: 
     int FuncA(int x); 
     int FuncB(int y); 

     int a; 
     int b; 
}; 

Ahora, sé que quedan dispuestas objetos de esta clase en la memoria con sólo los dos ints. Es decir, si hago un vector de instancias de la clase A, habrá dos ints para una instancia, seguidos de dos ints para la segunda instancia, etc. Los objetos son POD.

pero digamos que la clase tiene este aspecto:

class B 
{ 
    public: 
     int FuncA(int x); 
     int FuncB(int y); 
}; 

Qué hacer objetos de esta clase como mirada en la memoria? Si llene un vector con instancias de B ... ¿qué hay en el vector? Me han dicho que las funciones de miembros no virtuales se compilan finalmente como funciones gratuitas en algún lugar sin relación alguna con las instancias de la clase en la que se declaran (las funciones virtuales también lo son, pero los objetos almacenan un vtable con punteros de función) . Que las restricciones de acceso son meramente a nivel semántico, "humano". Solo los miembros de datos de una clase (y el vtable, etc.) realmente componen la estructura de memoria de los objetos.

De nuevo, ¿cómo son los objetos de la clase B en la memoria? ¿Es algún tipo de valor de marcador de posición? Algo tiene que estar allí, puedo tomar la dirección del objeto. Tiene que apuntar a algo. Sea lo que sea, ¿se permite al compilador alinear/optimizar estos objetos y tratar las llamadas a métodos como solo llamadas normales a funciones libres? Si creo un vector de estos y llamo al mismo método en cada objeto, ¿puede el compilador eliminar el vector y reemplazarlo con solo un montón de llamadas normales?

Solo tengo curiosidad.

+0

Se me ocurrió que si se desea una envoltura de encapsulación para las funciones que lleva * * hay espacio, se puede utilizar un espacio de nombres en lugar de una clase. Alternativamente, si hace que las funciones miembro estén estáticas, nunca necesitará crear una instancia de un objeto para acceder a ellas de manera similar, no requiere espacio. – Clifford

Respuesta

7

Todos los objetos en C++ están garantizados para tener un tamaño de> = 1 para que cada objeto tenga una dirección única.

No lo he probado, pero supongo que en su ejemplo, el compilador asignaría pero no inicializaría 1 byte para cada objeto de función en la matriz/vector.

4

¿Cómo son los objetos de esta clase en la memoria?

Todo depende del compilador. Una instancia de una clase vacía debe tener un tamaño distinto de cero, de modo que los objetos distintos tengan direcciones distintas (a menos que se instancia como una clase base de otra clase, en cuyo caso no puede ocupar ningún espacio). Típicamente, consistirá en un solo byte no inicializado.

Sea lo que sea, es el compilador permitió inline/optimizar estos objetos y tratar el método llama a las llamadas de función libres como algo normal?

Sí; el compilador no tiene que crear el objeto a menos que haga algo como tomar su dirección. Los objetos de función vacíos se usan bastante en la Biblioteca estándar, por lo que es importante que no introduzcan una sobrecarga innecesaria.

0

Todo lo que digo de aquí en adelante depende de la implementación, pero la mayoría de las implementaciones se ajustarán.

Si la clase tiene algún método virtual, habrá un miembro invisible del puntero vtable.Sin embargo, ese no es el caso con su ejemplo.

Sí, el compilador tratará una llamada a función miembro igual que una llamada a función libre, nuevamente a menos que sea una función virtual. Incluso si se trata de una función virtual, el compilador puede eludir el vtable si conoce el tipo concreto en el momento de la llamada. Cada llamada seguirá dependiendo del objeto, porque hay un parámetro invisible this con el puntero del objeto que se agrega a la llamada.

2

que realizó el siguiente experimento:

#include <iostream> 

class B 
{ 
    public: 
     int FuncA(int x); 
     int FuncB(int y); 
}; 

int main() 
{ 
    std::cout << sizeof(B) ; 
} 

El resultado fue 1 (VC++ 2010)

Me parece que la clase de hecho no requiere memoria en absoluto, pero que un objeto no puede ser cero tamaño ya que eso no tendría sentido semántico si tomas su dirección, por ejemplo. Esto es corroborado por la respuesta de Ferruccio.

5

Como dijo Ferruccio, se garantiza que todos los objetos en C++ tengan un tamaño de al menos 1. Es probable que sea de 1 byte, pero rellena el tamaño de la alineación, pero lo que sea .

Sin embargo, cuando se utiliza como una clase base, que no necesita para llenar cualquier espacio, de modo que:

class A {} a; // a is 1 byte. 
class B {} b; // b is 1 byte. 
class C { A a; B b;} c; // c is 2 bytes. 
class D : public A, B { } d; // d is 1 byte. 
class E : public A, B { char ee; } e; // e is only 1 byte 
0

Me gustaría pensar que acaba de ver como cualquier objeto en C++:

  • Cada instancia de la clase ocupa espacio. Debido a que los objetos en C++ deben tener un tamaño de al menos 1 (por lo que tienen direcciones únicas, como dijo Ferruccino), los objetos que no especifican ningún dato no reciben un tratamiento especial.
  • Las funciones no virtuales no ocupan ningún espacio en absoluto en una clase. Por el contrario, pueden ser consideradas como funciones de la siguiente manera:

    int B_FuncA(B *this, int x); 
    int B_FuncB(B *this, int y); 
    

Si esta clase puede ser utilizado por otros .cpp archivos, creo que estos se convertirán en instancias de clases reales, no funciones regulares.

Si solo desea que sus funciones sean libres en lugar de estar unidas a objetos, puede make them static o use a namespace.

0

Me han dicho que las funciones miembro no virtuales están en el final compilado como funciones gratuitas en algún lugar que no tienen relación con las instancias de la clase en la que están declarados (función virtual son demasiado, pero la tienda de objetos un vtable con indicadores de función). Que las restricciones de acceso son meramente a nivel semántico, "humano". Solo los miembros de datos de una clase (y el vtable, etc.) realmente componen la estructura de memoria de los objetos.

Sí, así es como funciona normalmente. Puede valer la pena señalar la distinción de que esto no está especificado en el estándar, y no es requerido - simplemente tiene sentido implementar clases como esta en el compilador.

De nuevo, ¿qué aspecto tienen los objetos de la clase B en la memoria? ¿Es algún tipo de valor de marcador de posición?Algo tiene que estar allí, puedo tomar la dirección del objeto

Exactamente. :) El estándar C++ requiere que los objetos ocupen al menos un byte, por exactamente la razón que usted dice. Debe tener una dirección, y si coloco estos objetos en una matriz, debo ser capaz de incrementar un puntero para obtener el objeto "siguiente", por lo que cada objeto debe tener una dirección única y ocupar al menos 1 byte. (Por supuesto, los objetos vacíos no hacer tienen que tomar exactamente 1 byte. Algunos compiladores pueden elegir para que sean 4 bytes, o cualquier otro tamaño, por razones de rendimiento)

Un compilador sensata ni siquiera hacerla un valor de marcador de posición sin embargo. ¿Por qué molestarse en escribir cualquier valor específico en este byte? Podemos dejar que contenga cualquier basura que haya tenido cuando se creó el objeto. Nunca se accederá de todos modos. Se ha asignado un solo byte, y nunca se ha leído o escrito.

Cuestiones relacionadas