Ihr Array wird auf dem Heap zugewiesen, und die Ints werden nicht eingerahmt.
Die Ursache Ihrer Verwirrung ist wahrscheinlich, dass Leute gesagt haben, dass Referenztypen auf dem Heap und Werttypen auf dem Stapel zugewiesen werden. Dies ist keine ganz genaue Darstellung.
Alle lokalen Variablen und Parameter werden auf dem Stapel zugeordnet. Dies umfasst sowohl Werttypen als auch Referenztypen. Der Unterschied zwischen den beiden ist nur das, was in der Variablen gespeichert ist. Es ist nicht überraschend, dass für einen Werttyp der Wert des Typs direkt in der Variablen gespeichert wird, und für einen Referenztyp wird der Wert des Typs auf dem Heap gespeichert, und ein Verweis auf diesen Wert wird in der Variablen gespeichert.
Gleiches gilt für Felder. Wenn Speicher für eine Instanz eines Aggregattyps (a class
oder a struct
) zugewiesen wird , muss er Speicher für jedes seiner Instanzfelder enthalten. Bei Feldern vom Referenztyp enthält dieser Speicher nur einen Verweis auf den Wert, der später selbst auf dem Heap zugewiesen wird. Bei Feldern vom Werttyp enthält dieser Speicher den tatsächlichen Wert.
Also, angesichts der folgenden Typen:
class RefType{
public int I;
public string S;
public long L;
}
struct ValType{
public int I;
public string S;
public long L;
}
Die Werte für jeden dieser Typen würden 16 Byte Speicher erfordern (unter der Annahme einer Wortgröße von 32 Bit). Das Feld benötigt I
jeweils 4 Bytes, um seinen Wert zu speichern, das Feld S
benötigt 4 Bytes, um seine Referenz zu speichern, und das Feld L
benötigt 8 Bytes, um seinen Wert zu speichern. Also der Speicher für den Wert von beiden RefType
und ValType
sieht so aus:
0 ┌────────────────────┐
│ ich │
4 ├────────────────────┤
│ S │
8 ├────────────────────┤
│ L │
│ │
16 └────────────────────┘
Nun , wenn Sie hatte drei lokale Variablen in einer Funktion, von Typen RefType
, ValType
und int[]
, wie folgt aus :
RefType refType;
ValType valType;
int[] intArray;
dann könnte Ihr Stapel folgendermaßen aussehen:
0 ┌────────────────────┐
│ refType │
4 ├────────────────────┤
│ valType │
│ │
│ │
│ │
20 ├────────────────────┤
│ intArray │
24 └────────────────────┘
Wenn Sie diesen lokalen Variablen Werte zugewiesen haben, wie folgt:
refType = new RefType();
refType.I = 100;
refType.S = "refType.S";
refType.L = 0x0123456789ABCDEF;
valType = new ValType();
valType.I = 200;
valType.S = "valType.S";
valType.L = 0x0011223344556677;
intArray = new int[4];
intArray[0] = 300;
intArray[1] = 301;
intArray[2] = 302;
intArray[3] = 303;
Dann könnte Ihr Stapel ungefähr so aussehen:
0 ┌────────────────────┐
│ 0x4A963B68 │ - Heap-Adresse von `refType`
4 ├────────────────────┤
│ 200 │ - Wert von `valType.I`
│ 0x4A984C10 │ - Heap-Adresse von `valType.S`
│ 0x44556677 │ - niedrige 32-Bit von `valType.L`
│ 0x00112233 │ - hohe 32-Bit von `valType.L`
20 ├────────────────────┤
│ 0x4AA4C288 │ - Heap-Adresse von `intArray`
24 └────────────────────┘
Speicher an Adresse 0x4A963B68
(Wert von refType
) wäre so etwas wie:
0 ┌────────────────────┐
│ 100 │ - Wert von `refType.I`
4 ├────────────────────┤
│ 0x4A984D88 │ - Heap-Adresse von `refType.S`
8 ├────────────────────┤
│ 0x89ABCDEF │ - niedrige 32-Bit von `refType.L`
│ 0x01234567 │ - hohe 32-Bit von `refType.L`
16 └────────────────────┘
Speicher an Adresse 0x4AA4C288
(Wert von intArray
) wäre so etwas wie:
0 ┌────────────────────┐
│ 4 │ - Länge des Arrays
4 ├────────────────────┤
│ 300 │ - `intArray [0]`
8 ├────────────────────┤
│ 301 │ - `intArray [1]`
12 ├────────────────────┤
│ 302 │ - `intArray [2]`
16 ├────────────────────┤
│ 303 │ - `intArray [3]`
20 └────────────────────┘
Wenn Sie nun an intArray
eine andere Funktion übergeben, lautet der auf den Stapel übertragene Wert 0x4AA4C288
die Adresse des Arrays und keine Kopie des Arrays.