die Standard-C++ gibt an, dass:
- Objekte eine Ausrichtungs Anforderung haben, von denen ihre Größe ein Vielfaches ist (also wenn
int
4 Bytes breit ist, dann ist es eine Ausrichtung von 1, 2 oder 4 Bytes erfordert, abhängig von der Implementierung).
- Mitgliedsobjekte (wenn sie durch Zugriffsbezeichner wie
public
nicht getrennt sind) sind alle in der Reihenfolge, wie sie
- und sie respektieren Anforderungen ihrer Ausrichtung zugeordnet deklariert sind zugeordnet.
Also nein, der Standard sagt nicht genau, dass die Klasse eine Größe von 12 Bytes haben sollte.
Aber es tut sagen, dass b
nach a
zugewiesen werden soll, und dass c
soll nach b
zugeordnet werden.
Auf einer Plattform, wo int
4 Bytes breit ist, und erfordert eine 4-Byte-Ausrichtung, lässt dies 12 Bytes als die kleinste gültige Größe:
a
nimmt den ersten 4 Bytes
b
ein Byte dauert
c
benötigt 4 Bytes, aber muss auf einer 4-Byte-Grenze zugewiesen werden.b
endete ein Byte über so eine Grenze, so wird die nächste gültige Position c
bei wird durch Einfügen von 3 Bytes Polsterung gefunden.
So ist die Gesamtgröße der Klasse endet als die Größe der Elemente bis (4 + 1 + 4 = 9) und drei Bytes von Polstern, für insgesamt 12
Es ist eine andere Regel Das hat hier keine Auswirkungen, aber was wäre von Bedeutung, wenn Sie stattdessen die Mitglieder in der Reihenfolge definiert hätten.
Die enthaltene Klasse (A
) erbt die Ausrichtungsanforderung vom am strengsten ausgerichteten Element des Elements. Das heißt, da es einen int
enthält, hat es die gleiche Ausrichtungsanforderung wie ein int
tut. Und da die Gesamtgröße des Objekts ein Vielfaches seiner Ausrichtungsanforderung sein muss, würde eine Klasse, die die Elemente in der Reihenfolge noch enthält, 12 Byte Speicherplatz benötigen. Es würde nur die 3 Bytes der Auffüllung an das Ende der Klasse statt zwischen b
und c
verschieben.
In einigen anderen Fällen jedoch kann das Umordnen von Elementen in absteigender Reihenfolge der Größe manchmal die Größe einer Klasse reduzieren.
Angenommen, wir stattdessen eine Klasse wie diese gehabt hatten:
class B {
char a;
double b;
int c;
};
Dies würde 24 Byte Speicher erforderlich ist (1 Byte für a
, 8 Byte für b
und 4 Bytes für c
, aber dann Stellen Sie sicher, b
endet auf einer 8-Byte-Grenze, würden wir Bytes der Auffüllung zwischen a
und b
benötigen, und um sicherzustellen, dass die gesamte Klasse endet mit einer Größe, die ein Vielfaches von 8 ist, benötigen wir weitere 4 Bytes nach c
Aber Neuordnen die Mitglieder nach Größe, wie folgt aus:
class B {
double b;
int c;
char a;
};
Ergebnisse in einer Klasse erfordern nur 16 Byte:
das gleiche 1 + 4 + 8 Bytes für das Mitglied selbst Objekte, aber jetzt c
ist bereits auf einer 4-Byte-Grenze ausgerichtet (weil es nach b
kommt, die an einer 8-Byte-Grenze endet), und a
braucht nie eine Ausrichtung, so dass die einzige Ausrichtung, die wir brauchen, ist sicherzustellen, dass B
eine Größe hat, die ein Vielfaches ist von 8. Die Mitglieder nehmen 13 Bytes, so dass wir 3 Bytes der Auffüllung hinzufügen können, und die Klasse endet bei 16 Bytes, 33% kleiner tha n der ersten Version.
Sie können auch darauf hinweisen, dass auf den meisten Architekturen der Zugriff auf ein falsch ausgerichtetes Objekt zu einer Art Busfehler führt, der das Programm zum Absturz bringt. Auf einem Intel wird das Programm nicht abstürzen, aber es wird immer noch viel langsamer laufen, wenn die Daten falsch ausgerichtet sind. –