2010-03-18 16 views
7

La dimensione di una classe senza membri di dati viene restituita come 1 byte, anche se è stato dichiarato un puntatore implicito "questo". Non dovrebbe la dimensione restituita essere 4 byte (su una macchina a 32 bit)? Mi sono imbattuto in articoli che indicavano che "questo" puntatore non viene conteggiato per il calcolo della dimensione dell'oggetto. Ma non sono in grado di capire la ragione di ciò. Inoltre, se una funzione membro viene dichiarata virtuale, la dimensione della classe viene ora restituita come 4 byte. Ciò significa che il vptr viene conteggiato per il calcolo della dimensione dell'oggetto. Perché il vptr è considerato e il puntatore "this" ignorato per il calcolo della dimensione dell'oggetto?Dimensioni di una classe con puntatore "this"

+0

duplicati: http://stackoverflow.com/questions/621616/c-che-è-il-size-of-an-object-of-an-empty-class http://stackoverflow.com/questions/2362097/empty-class-in-c –

risposta

6

Il puntatore this non è membro della classe. È solo un costrutto che viene utilizzato nei metodi appartenenti alla classe per fare riferimento all'istanza corrente.

Se si dispone di una classe come questa:

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

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

public: 
    int _a; 
    int _b; 
}; 

Questa classe ha solo bisogno di spazio per due istanze di int per ogni istanza. Dopo aver creato un'istanza e eseguito il metodo sum(), tale metodo viene chiamato con un puntatore all'istanza, ma tale puntatore viene sempre da un'altra parte, non viene archiviato nell'istanza dell'oggetto.

Ad esempio:

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

cout << fib12->sum(); 

Si noti come la variabile che diventa il puntatore this è memorizzato fuori l'oggetto, nell'ambito che lo ha creato.

Si potrebbe, infatti, di trasformare sempre un metodo come quello sopra in:

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

Se quanto sopra è definito all'interno della classe (in modo che possa accedere ai membri privati), non c'è alcuna differenza. In realtà, questo è come i metodi vengono implementati dietro la scena; il puntatore this è solo un argomento nascosto per tutti i metodi membro.

La chiamata sarebbe diventato:

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

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

'questo', non viene memorizzato come un membro di dati nella classe, è solo un 'puntatore' per l'istanza della classe. Consideralo come un 'argomento nascosto' passato al metodo. Infatti, su sistemi Win32 viene spesso passato nel registro di ecx (non come eax come pensavo inizialmente).

Non appena si dispone di 1 o più metodi virtuali, l'applicazione richiede un modo per archiviare i puntatori ai metodi virtuali. Questo è chiamato vtable, che è identico per tutte le istanze della stessa classe. Poiché è necessario sapere in fase di esecuzione quale metodo 'esplicito' chiamare per quale 'metodo virtuale' un puntatore al vtable è memorizzato nell'istanza della classe. Quindi il vtable-pointer (o vptr) ha bisogno di 4 byte (o 8 byte su un sistema a 64 bit).

+1

Ho pensato che fosse passato in 'ecx'. – Blindy

+0

Oops, sì hai ragione. eax viene utilizzato per il valore restituito. (Ho modificato il post) – Patrick

2

Questo puntatore non è memorizzato all'interno dell'oggetto. Non c'è bisogno di farlo. Hai già un puntatore o un oggetto su cui richiamare le funzioni. Per quanto riguarda la dimensione di 1, lo standard C++ richiede che gli oggetti distict abbiano indirizzi distinti.

-1

La dimensione di un puntatore è sempre la dimensione del tipo di puntatore richiesto per essere memorizzato.

Ad esempio, se l'indirizzo di memoria di un int è 32 bit su un'architettura a 64 bit, allora

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

+0

inoltre che sizeof() restituisce il numero di byte, non i bit, sizeof (int *) e sizeof (int **) non possono essere diversi. – PlasmaHH

Problemi correlati