2010-03-18 14 views
7

El tamaño de una clase sin miembros de datos se devuelve como 1 byte, aunque haya un puntero 'this' implícito declarado. ¿No debería el tamaño devuelto ser de 4 bytes (en una máquina de 32 bits)? Encontré artículos que indicaban que "este" puntero no cuenta para calcular el tamaño del objeto. Pero no puedo entender la razón de esto. Además, si cualquier función miembro se declara virtual, el tamaño de la clase ahora se devuelve como 4 bytes. Esto significa que el vptr se cuenta para calcular el tamaño del objeto. ¿Por qué se considera el vptr y se ignora este puntero para calcular el tamaño del objeto?Tamaño de una clase con el puntero 'this'

+0

duplicados: http://stackoverflow.com/questions/621616/c-what-is-the-size-of-an-object-of-an-empty-class http://stackoverflow.com/questions/2362097/empty-class-in-c –

Respuesta

6

El puntero this no es un miembro de la clase. Es solo una construcción que se usa en métodos que pertenecen a la clase para referirse a la instancia actual.

Si usted tiene una clase como esta:

class IntPair 
{ 
public: 
    IntPair(int a, int b) : _a(a), _b(b) { } 

    int sum() const { return _a + _b; } 

public: 
    int _a; 
    int _b; 
}; 

Esta clase sólo tiene espacio para dos instancias de int para cada instancia. Una vez que ha creado una instancia y está ejecutando el método sum(), se llama a ese método con un puntero a la instancia, pero ese puntero siempre viene de otro lugar, no se almacena en la instancia del objeto.

Por ejemplo:

IntPair *fib12 = new IntPair(89, 144); 

cout << fib12->sum(); 

Note como la variable que se convierte en el puntero this se almacena fuera del objeto, en el ámbito que lo creó.

Usted podría, de hecho, siempre transformar un método similar a la anterior en:

static int sum2(const IntPair* instance) 
{ 
    return instance->_a + instance->_b; 
} 

Si lo anterior se define dentro de la clase (por lo que se puede tener acceso a los miembros privados), no hay ninguna diferencia. De hecho, este es cómo se implementan los métodos detrás de la escena; el puntero this es solo un argumento oculto para todos los métodos miembros.

La llamada se convertiría en:

IntPair* fib12 = new IntPair(89, 144); 

cout << IntPair::sum2(fib12); 
4

'esto' no se almacena como un miembro de datos en la clase, que es sólo un 'puntero' a la instancia de la clase. Considérelo como un "argumento oculto" pasado al método. De hecho, en los sistemas Win32 a menudo se pasa en el registro ecx (no eax como pensé inicialmente).

Tan pronto como tenga 1 o más métodos virtuales, su aplicación necesita una manera de almacenar los punteros a los métodos virtuales. Esto se llama vtable, que es idéntico para todas las instancias de la misma clase. Dado que necesita saber en tiempo de ejecución qué método 'explícito' para llamar para qué 'método virtual' se almacena un puntero al vtable en la instancia de la clase. Por lo tanto, el vtable-pointer (o vptr) necesita 4 bytes (u 8 bytes en un sistema de 64 bits).

+1

Pensé que se pasó en 'ecx'. – Blindy

+0

Oops, sí, tienes razón. eax se utiliza para el valor de retorno. (edité la publicación) – Patrick

2

Este puntero no se almacena dentro del objeto. No hay necesidad de hacer eso. Ya tiene un puntero o un objeto para invocar las funciones. En cuanto al tamaño de 1, el estándar de C++ requiere que los objetos distict tengan direcciones distintas.

-1

El tamaño de un puntero es siempre el tamaño del tipo de puntero requerido para almacenarse en la memoria.

Por ejemplo, si la dirección de memoria de un int es de 32 bits en una arquitectura de 64 bits, a continuación,

int a = 10; int * b = & a; sizeof (b); // 32 sizeof (& b); 64

+0

además de que sizeof() devuelve el número de bytes, no bits, sizeof (int *) y sizeof (int **) no pueden ser diferentes. – PlasmaHH

Cuestiones relacionadas