Suche…


Bemerkungen

Siehe auch Größe der Integraltypen .

Klassenarten

Mit "Klasse" meinen wir einen Typ, der mit dem Schlüsselwort class oder struct definiert wurde (nicht jedoch mit enum struct oder enum class ).

  • Selbst eine leere Klasse belegt immer noch mindestens ein Byte Speicherplatz. es wird also nur aus Polsterung bestehen. Dies stellt sicher, dass wenn p auf ein Objekt einer leeren Klasse zeigt, p + 1 eine eindeutige Adresse ist und auf ein bestimmtes Objekt zeigt. Es ist jedoch möglich, dass eine leere Klasse eine Größe von 0 hat, wenn sie als Basisklasse verwendet wird. Siehe leere Basisoptimierung .

    class Empty_1 {};                               // sizeof(Empty_1)       == 1
    class Empty_2 {};                               // sizeof(Empty_2)       == 1
    class Derived : Empty_1 {};                     // sizeof(Derived)       == 1
    class DoubleDerived : Empty_1, Empty_2 {};      // sizeof(DoubleDerived) == 1
    class Holder { Empty_1 e; };                    // sizeof(Holder)        == 1
    class DoubleHolder { Empty_1 e1; Empty_2 e2; }; // sizeof(DoubleHolder)  == 2
    class DerivedHolder : Empty_1 { Empty_1 e; };   // sizeof(DerivedHolder) == 2
    
  • Die Objektdarstellung eines Klassentyps enthält die Objektdarstellungen der Basisklassen- und nicht statischen Elementtypen. Daher zum Beispiel in der folgenden Klasse:

    struct S {
        int x;
        char* y;
    };
    

    Es gibt eine aufeinanderfolgende Folge von sizeof(int) Bytes innerhalb eines S Objekts, das als Unterobjekt bezeichnet wird und den Wert von x , und ein anderes Subobjekt mit sizeof(char*) Bytes, das den Wert von y . Die beiden können nicht verschachtelt werden.

  • Wenn ein Klassentyp Member und / oder Basisklassen mit den Typen t1, t2,...tN , muss die Größe mindestens die sizeof(t1) + sizeof(t2) + ... + sizeof(tN) wenn die vorstehenden Punkte angegeben sind . Abhängig von den Ausrichtungsanforderungen der Member und der Basisklassen kann der Compiler jedoch gezwungen sein, die Auffüllung zwischen Unterobjekten oder am Anfang oder Ende des vollständigen Objekts einzufügen.

    struct AnInt      { int i; };
      // sizeof(AnInt)        == sizeof(int)
      // Assuming a typical 32- or 64-bit system, sizeof(AnInt)        == 4 (4).
    struct TwoInts    { int i, j; };
      // sizeof(TwoInts)      >= 2 * sizeof(int)
      // Assuming a typical 32- or 64-bit system, sizeof(TwoInts)      == 8 (4 + 4).
    struct IntAndChar { int i; char c; };
      // sizeof(IntAndChar)   >= sizeof(int) + sizeof(char)
      // Assuming a typical 32- or 64-bit system, sizeof(IntAndChar)   == 8 (4 + 1 + padding).
    struct AnIntDerived : AnInt { long long l; };
      // sizeof(AnIntDerived) >= sizeof(AnInt) + sizeof(long long)
      // Assuming a typical 32- or 64-bit system, sizeof(AnIntDerived) == 16 (4 + padding + 8).
    
  • Wenn aufgrund von Ausrichtungsanforderungen ein Abstand in ein Objekt eingefügt wird, ist die Größe größer als die Summe der Größen der Elemente und Basisklassen. Bei einer Ausrichtung von n Byte ist size normalerweise das kleinste Vielfache von n das größer ist als die Größe aller Member und Basisklassen. Jedes Mitglied memN wird typischerweise an einer Adresse angeordnet werden , der ein Vielfaches von ist alignof(memN) , und n ist typischerweise die größte sein alignof out aller Mitglieder alignof s. Wenn ein Glied mit einem kleineren alignof von einem Glied mit einem größeren alignof , besteht daher die Möglichkeit, dass das letztere Glied nicht richtig ausgerichtet wird, wenn es unmittelbar nach dem ersteren platziert wird. In diesem Fall wird eine Polsterung (auch als Ausrichtungselement bekannt ) zwischen den beiden Elementen angeordnet, so dass das letztere Element seine gewünschte Ausrichtung haben kann. Wenn im alignof zu einem alignof mit einem größeren alignof ein alignof mit einem kleineren alignof , ist normalerweise kein Auffüllen erforderlich. Dieser Vorgang wird auch als "Packen" bezeichnet.
    Da Klassen normalerweise das alignof ihres Mitglieds mit dem größten alignof , werden Klassen normalerweise an dem alignof des größten eingebauten Typs ausgerichtet, den sie direkt oder indirekt enthalten.

    // Assume sizeof(short) == 2, sizeof(int) == 4, and sizeof(long long) == 8.
    // Assume 4-byte alignment is specified to the compiler.
    struct Char { char c; };
      // sizeof(Char)                == 1 (sizeof(char))
    struct Int  { int i; };
      // sizeof(Int)                 == 4 (sizeof(int))
    struct CharInt { char c; int i; };
      // sizeof(CharInt)             == 8 (1 (char) + 3 (padding) + 4 (int))
    struct ShortIntCharInt { short s; int i; char c; int j; };
      // sizeof(ShortIntCharInt)     == 16 (2 (short) + 2 (padding) + 4 (int) + 1 (char) +
      //                                    3 (padding) + 4 (int))
    struct ShortIntCharCharInt { short s; int i; char c; char d; int j; };
      // sizeof(ShortIntCharCharInt) == 16 (2 (short) + 2 (padding) + 4 (int) + 1 (char) +
      //                                    1 (char) + 2 (padding) + 4 (int))
    struct ShortCharShortInt { short s; char c; short t; int i; };
      // sizeof(ShortCharShortInt)   == 12 (2 (short) + 1 (char) + 1 (padding) + 2 (short) +
      //                                    2 (padding) + 4 (int))
    struct IntLLInt { int i; long long l; int j; };
      // sizeof(IntLLInt)            == 16 (4 (int) + 8 (long long) + 4 (int))
      // If packing isn't explicitly specified, most compilers will pack this as
      //   8-byte alignment, such that:
      // sizeof(IntLLInt)            == 24 (4 (int) + 4 (padding) + 8 (long long) +
      //                                    4 (int) + 4 (padding))
    
    // Assume sizeof(bool) == 1, sizeof(ShortIntCharInt) == 16, and sizeof(IntLLInt) == 24.
    // Assume default alignment: alignof(ShortIntCharInt) == 4, alignof(IntLLInt) == 8.
    struct ShortChar3ArrShortInt {
        short s;
        char c3[3];
        short t;
        int i;
    };
      // ShortChar3ArrShortInt has 4-byte alignment: alignof(int) >= alignof(char) &&
      //                                             alignof(int) >= alignof(short)
      // sizeof(ShortChar3ArrShortInt) == 12 (2 (short) + 3 (char[3]) + 1 (padding) +
      //                                      2 (short) + 4 (int))
      // Note that t is placed at alignment of 2, not 4.  alignof(short) == 2.
    
    struct Large_1 {
        ShortIntCharInt sici;
        bool b;
        ShortIntCharInt tjdj;
    };
      // Large_1 has 4-byte alignment.
        // alignof(ShortIntCharInt) == alignof(int) == 4
        // alignof(b) == 1
        // Therefore, alignof(Large_1) == 4.
      // sizeof(Large_1) == 36 (16 (ShortIntCharInt) + 1 (bool) + 3 (padding) +
      //                        16 (ShortIntCharInt))
    struct Large_2 {
        IntLLInt illi;
        float f;
        IntLLInt jmmj;
    };
      // Large_2 has 8-byte alignment.
        // alignof(IntLLInt) == alignof(long long) == 8
        // alignof(float) == 4
        // Therefore, alignof(Large_2) == 8.
      // sizeof(Large_2) == 56 (24 (IntLLInt) + 4 (float) + 4 (padding) + 24 (IntLLInt))
    
C ++ 11
  • Wenn strenge Ausrichtung mit alignas erzwungen wird, wird der Typ durch Auffüllen mit dem alignas gezwungen, die angegebene Ausrichtung zu erfüllen, selbst wenn er sonst kleiner wäre. Bei der folgenden Definition werden in Chars<5> am Ende drei (oder möglicherweise mehr) Auffüllbytes eingefügt, so dass die Gesamtgröße 8 beträgt. Es ist nicht möglich, dass eine Klasse mit einer Ausrichtung von 4 eine Größe hat von 5, da es unmöglich ist, ein Array dieser Klasse zu erstellen, so dass die Größe auf ein Vielfaches von 4 "aufgerundet" werden muss, indem Auffüllbytes eingefügt werden.

    // This type shall always be aligned to a multiple of 4.  Padding shall be inserted as
    // needed.
    // Chars<1>..Chars<4> are 4 bytes, Chars<5>..Chars<8> are 8 bytes, etc.
    template<size_t SZ>
    struct alignas(4) Chars { char arr[SZ]; };
    
    static_assert(sizeof(Chars<1>) == sizeof(Chars<4>), "Alignment is strict.\n");
    
  • Wenn zwei nicht statische Member einer Klasse denselben Zugriffsbezeichner haben , wird derjenige, der später in der Deklarationsreihenfolge erscheint, später in der Objektdarstellung garantiert. Wenn jedoch zwei nicht statische Member unterschiedliche Zugriffsspezifizierer haben, ist ihre relative Reihenfolge innerhalb des Objekts nicht spezifiziert.
  • Es ist nicht festgelegt, in welcher Reihenfolge die Basisklassen-Unterobjekte in einem Objekt angezeigt werden, ob sie nacheinander auftreten und ob sie vor, nach oder zwischen untergeordneten Unterobjekten erscheinen.

Arithmetische arten

Schmale Zeichentypen

Der unsigned char Typ verwendet alle Bits, um eine Binärzahl darzustellen. Wenn also unsigned char 8 Bit lang ist, repräsentieren die 256 möglichen Bitmuster eines char Objekts die 256 verschiedenen Werte {0, 1, ..., 255}. Die Zahl 42 wird garantiert durch das Bitmuster 00101010 .

Der signed char hat keine Auffüllbits, dh wenn das signed char Zeichen 8 Bit lang ist, hat es eine Kapazität von 8 Bit, um eine Zahl darzustellen.

Beachten Sie, dass diese Garantien nicht für andere Typen als schmale Zeichentypen gelten.

Integer-Typen

Die vorzeichenlosen Integer-Typen verwenden ein reines Binärsystem, können jedoch Füllbits enthalten. Zum Beispiel ist es möglich (wenn auch unwahrscheinlich), dass das unsigned int 64 Bit lang ist, aber nur Ganzzahlen zwischen 0 und 2 32-1 einschließlich speichern kann. Die anderen 32 Bits wären Auffüllbits, die nicht direkt beschrieben werden sollten.

Die vorzeichenbehafteten Integer-Typen verwenden ein binäres System mit Vorzeichenbit und möglicherweise Füllbits. Werte, die zum allgemeinen Bereich eines vorzeichenbehafteten Integer-Typs und des entsprechenden vorzeichenlosen Integer-Typs gehören, haben dieselbe Darstellung. Wenn beispielsweise das Bitmuster 0001010010101011 eines unsigned short Objekts unsigned short den Wert 5291 , dann repräsentiert es auch den Wert 5291 wenn es als short Objekt interpretiert wird.

Es ist implementierungsdefiniert, ob eine Zwei-Komplement-, Ein-Komplement- oder Vorzeichengrößen-Darstellung verwendet wird, da alle drei Systeme die Anforderung des vorherigen Abschnitts erfüllen.

Fließkomma-Typen

Die Wertdarstellung von Gleitkommatypen ist implementierungsdefiniert. Am häufigsten entsprechen die float und double Typen IEEE 754 und sind 32 und 64 Bit lang (so hätte float beispielsweise eine Genauigkeit von 23 Bit, die 8 Exponenten-Bits und 1 Vorzeichen-Bits folgen würde). Der Standard garantiert jedoch nichts. Gleitkommatypen haben häufig "Trap-Darstellungen", die Fehler verursachen, wenn sie in Berechnungen verwendet werden.

Arrays

Ein Array-Typ hat keine Auffüllung zwischen seinen Elementen. Daher ist ein Array mit dem Elementtyp T nur eine Folge von T Objekten, die in der Reihenfolge angeordnet sind.

Ein mehrdimensionales Array ist ein Array von Arrays, und das oben Gesagte gilt rekursiv. Zum Beispiel, wenn wir die Erklärung haben

int a[5][3];

dann a ist ein Array von Arrays von 5 3 int s. Daher ist a[0] , die aus den drei Elementen a[0][0] , a[0][1] , a[0][2] besteht, vor a[1] , die besteht, im Speicher abgelegt von a[1][0] , a[1][1] und a[1][2] . Dies wird als Reihenhauptordnung bezeichnet .



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow