Sök…


Anmärkningar

Se även storlek på integrerade typer .

Klasstyper

Med "klass" menar vi en typ som definierades med hjälp av sökordet class eller struct (men inte enum struct eller enum class ).

  • Även en tom klass upptar fortfarande minst en byte av lagring; den kommer därför att bestå enbart av stoppning. Detta säkerställer att om p pekar på ett objekt i en tom klass, så är p + 1 en distinkt adress och pekar på ett distinkt objekt. Det är dock möjligt för en tom klass att ha storleken 0 när den används som basklass. Se tom basoptimering .

    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
    
  • Objektrepresentationen av en klasstyp innehåller objektrepresentationen av basklassen och icke-statiska medlemstyper. Därför till exempel i följande klass:

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

    det finns en i följd sekvens av sizeof(int) byte i ett S objekt, kallat ett subobjekt, som innehåller värdet på x , och ett annat subobjekt med sizeof(char*) byte som innehåller värdet på y . De två kan inte läggas samman.

  • Om en klasstyp har medlemmar och / eller basklasser med typerna t1, t2,...tN , måste storleken vara minst sizeof(t1) + sizeof(t2) + ... + sizeof(tN) med de föregående punkterna . Beroende på anpassningskraven för medlemmarna och basklasserna kan kompilatorn emellertid tvingas införa stoppning mellan underobjekt eller i början eller slutet av det kompletta objektet.

    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).
    
  • Om stoppning införs i ett objekt på grund av justeringskraven, kommer storleken att vara större än summan av storlekarna på elementen och basklasserna. Med n byte-inriktning är storlek typiskt den minsta multipeln av n som är större än storleken på alla medlemmar och basklasser. Varje memN kommer vanligtvis att placeras på en adress som är en multipel av alignof(memN) , och n typiskt den största alignof av alla medlemmars alignof . På grund av detta, om ett medlem med en mindre alignof följs av ett medlem med en större alignof , finns det en möjlighet att det senare medlemmet inte kommer att justeras ordentligt om det placeras omedelbart efter det förstnämnda. I detta fall kommer stoppning (även känd som ett inriktningselement ) att placeras mellan de två delarna, så att det senare elementet kan ha sin önskade inriktning. Omvänt, om en medlem med en större alignof följs av en medlem med en mindre alignof , alignof ingen stoppning. Denna process kallas också "packning".
    På grund av att klasser vanligtvis delar deras alignof med den största alignof , kommer klasser vanligtvis att anpassas till alignof av den största inbyggda typen som de direkt eller indirekt innehåller.

    // 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
  • Om strikt inriktning tvingas med alignas , kommer stoppning att användas för att tvinga typen att uppfylla den angivna inriktningen, även om den annars skulle vara mindre. Till exempel, med definitionen nedan, kommer Chars<5> att ha tre (eller eventuellt fler) stoppningsbyte infogade i slutet så att dess totala storlek är 8. Det är inte möjligt för en klass med en justering av 4 att ha en storlek av 5 eftersom det skulle vara omöjligt att göra en grupp av den klassen, så storleken måste "rundas upp" till ett multipel av 4 genom att sätta in vadderingsbyte.

    // 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");
    
  • Om två icke-statiska medlemmar i en klass har samma åtkomstspecifikation , kommer den som kommer senare i deklarationsordning garanteras att komma senare i objektrepresentationen. Men om två icke-statiska medlemmar har olika åtkomstspecifikationer, är deras relativa ordning inom objektet inte specificerad.
  • Det är ospecificerat i vilken ordning basklassobjekt visas i ett objekt, om de förekommer i följd och om de visas före, efter eller mellan medlemsobjekt.

Aritmetiska typer

Smala karaktärstyper

Den unsigned char typen använder alla bitar för att representera ett binärt tal. Därför, till exempel, om unsigned char är 8 bitar lång, representerar de 256 möjliga bitmönstren för ett char objekt de 256 olika värdena {0, 1, ..., 255}. Siffran 42 kommer garanterat att representeras av bitmönstret 00101010 .

Den signed char typen har inga stoppningsbitar, dvs om signed char är 8 bitar lång, har den 8 bitar kapacitet att representera ett nummer.

Observera att dessa garantier inte gäller andra typer än smala karaktärstyper.

Heltalstyper

De osignerade heltalstyperna använder ett rent binärt system, men kan innehålla stoppningsbitar. Till exempel är det möjligt (även om det är osannolikt) för unsigned int att vara 64 bitar långa men bara kunna lagra heltal mellan 0 och 2 32 - 1 inklusive. De andra 32 bitarna skulle vara vadderingsbitar, som inte borde skrivas till direkt.

De signerade heltalstyperna använder ett binärt system med en teckenbit och eventuellt vadderingsbitar. Värden som tillhör det gemensamma intervallet för en signerad heltalstyp och motsvarande osignerad heltalstyp har samma representation. Till exempel, om bitmönstret 0001010010101011 av ett unsigned short objekt representerar värdet 5291 , då det representerar även värdet 5291 , när tolkas som en short objekt.

Det definieras av implementeringen om en två komplement, ens komplement eller teckenstorleksrepresentation används, eftersom alla tre system uppfyller kravet i föregående stycke.

Flytande punkttyper

Värdesrepresentationen av flytande punkttyper är implementeringsdefinerad. Vanligtvis överensstämmer float och double med IEEE 754 och är 32 och 64 bitar långa (så till exempel skulle float ha 23 bitar med precision som skulle följa 8 exponentbitar och 1 teckenbit). Men standarden garanterar ingenting. Flytande punkttyper har ofta "trap-representationer", vilket orsakar fel när de används i beräkningar.

arrayer

En array-typ har ingen stoppning mellan dess element. Därför, en array med elementtypen T är bara en sekvens av T -objekt läggs ut i minnet, i ordning.

En flerdimensionell matris är en matris med matriser, och ovanstående gäller rekursivt. Om vi till exempel har deklarationen

int a[5][3];

a är en array av 5 uppsättningar av 3 int s. Därför läggs a[0] , som består av de tre elementen a[0][0] , a[0][1] , a[0][2] , i minnet före a[1] , som består av a[1][0] , a[1][1] och a[1][2] . Detta kallas radordning för rad .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow