2016-05-15 4 views
2

Kann mir jemand helfen, das Verhalten des Operators sizeof() zu verstehen?Warum ist die Größe meiner Klasse größer als die Summe ihrer Mitglieder?

#include <iostream> 

using namespace std; 

class A{ 
    int first; 
    double last; 
    public: 
    A(int a) 
    { 
     cout << a << endl; 
    } 
}; 
int main() 
{ 
    A a(3); 
    cout << sizeof(a) << endl; 
    return 0; 
} 

Dieser Code druckt mir Größe von a als 16 Bytes. Die Größe der Klasse wird basierend auf ihren Mitgliedern berechnet. Also habe ich 4 Bytes (int) + 8 Bytes (double) = 12.

Also warum habe ich 16 Bytes bekommen?

Wenn ich int und double Mitglieder auskommentieren bekomme ich 1 Byte.

+0

Wenn Sie Visual C++ verwenden, finden Sie https://msdn.microsoft.com/en-us/library/xh3e3fd0.aspx und versuchen, die '/ Zp1' Option, um den Ausgang 12 –

+0

Nein zu machen, ich gewöhnlichen g ++ verwenden Compiler –

+0

GCC ist so "normal" wie Visual C++ :) In jedem Fall bietet jeder C++ - Compiler ähnliche Optionen. Dieses Zeug ist inhärent implementierungsspezifisch. –

Antwort

1

Der Compiler legt die Klasse Interieur für Geschwindigkeit und andere Faktoren aus, die nicht unbedingt für platzsparende, so könnte es einen leeren 4-Byte-Block hinter einer Größe-4-Element verlassen, bevor das nächste Element passt. Dies macht den Zugriff auf das nächste Element in der modernen Architektur (die 64-Bit-basiert = 8 Byte ist) schneller.

Beachten Sie auch, dass die Größe eines Klassenobjekts andere Daten enthalten kann, die Ihnen nicht bekannt sind, wie Zeiger auf virtuelle Funktionstabellen usw. Es ist die Aufgabe des Compilers, das Endgültige zu setzen Code läuft korrekt und schnell.

+0

Dies ist meistens richtig, außer dass die Art und Weise, wie der Compiler die Klasse anlegt, nicht unbedingt auf Geschwindigkeit optimiert ist. Andere Faktoren werden ebenfalls berücksichtigt. Insbesondere wenn eine Plattform eine suboptimale ABI hat, die von anderen Compilern verwendet wird, dann können neue Compiler diese ABI aus Kompatibilitätsgründen verwenden, selbst wenn sie durch das Wegfallen der Kompatibilität einen schnelleren ABI erhalten könnten. – hvd

+0

Ich denke, dass virtuelle Funktionstabellen als eine Eigenschaft der gesamten Klasse und nicht mit jeder Instanz der Klasse gespeichert werden. –

1

Das Layout der Felder in der Klasse ist implementierungsdefiniert, solange POD-Klassen mit C-Strukturen kompatibel sind. Aber selbst in C-Structs-Implementierungen fügen Sie Padding aus verschiedenen Gründen, z. B. der Leistung, hinzu. Daher fügt der Compiler nach dem Feld wahrscheinlich vier Byte Padding hinzu, um das Feld double bei einer ausgerichteten 8-Byte-Adresse zu starten.

Wenn Sie dies speziell nicht benötigen, gibt es Möglichkeiten, die Ausrichtung und Auffüllung von Klassen/Strukturen zu steuern, die zwischen den Compilern variieren. Zum Beispiel hat GCC eine ähnliche Syntax wie __attribute__((packed)), die diese Auffüllung entfernen wird. Dies ist nur selten erforderlich - vor allem, wenn die Struktur einem Geräteverzeichnis zugeordnet werden muss - und beeinträchtigt normalerweise die Leistung. Vermeiden Sie sie daher, wenn dies möglich ist.

0

Die Standardmethode, mit der der Compiler Mitglieder in eine Klasse packt, ist, mit Wortgrenzen, d. H. Vielfachen der Größe eines Wortes (8 Bytes auf 64-Bit-Maschine), auszurichten. Um das Packen zu stoppen, verwenden Sie #pragma pack(1) oder die Compileroption /Zp. Dies zwingt den Compiler, die Mitglieder gegeneinander zu zerquetschen.

Eine Klasse darf keine Nullgröße haben, da dies bedeuten kann, dass die Zeiger auf zwei verschiedene Objekte gleich sind und daher eine Mindestgröße von 1 Byte haben.

+0

Ja, danke. Es macht Sinn. –

Verwandte Themen