Votre tableau est alloué sur le tas et les entiers ne sont pas encadrés.
La source de votre confusion est probablement parce que les gens ont dit que les types de référence sont alloués sur le tas et que les types de valeur sont alloués sur la pile. Ce n'est pas une représentation entièrement exacte.
Toutes les variables et paramètres locaux sont alloués sur la pile. Cela inclut à la fois les types de valeur et les types de référence. La différence entre les deux est uniquement ce qui est stocké dans la variable. Sans surprise, pour un type valeur, la valeur du type est stockée directement dans la variable, et pour un type référence, la valeur du type est stockée sur le tas, et une référence à cette valeur est ce qui est stocké dans la variable.
Il en va de même pour les champs. Lorsque la mémoire est allouée pour une instance d'un type d'agrégat (a class
ou a struct
), elle doit inclure le stockage pour chacun de ses champs d'instance. Pour les champs de type référence, ce stockage contient simplement une référence à la valeur, qui serait elle-même allouée ultérieurement sur le tas. Pour les champs de type valeur, ce stockage contient la valeur réelle.
Donc, étant donné les types suivants:
class RefType{
public int I;
public string S;
public long L;
}
struct ValType{
public int I;
public string S;
public long L;
}
Les valeurs de chacun de ces types nécessiteraient 16 octets de mémoire (en supposant une taille de mot de 32 bits). Le champ I
dans chaque cas prend 4 octets pour stocker sa valeur, le champ S
prend 4 octets pour stocker sa référence et le champ L
prend 8 octets pour stocker sa valeur. Donc, la mémoire pour la valeur des deux RefType
et ValType
ressemble à ceci:
0 ┌───────────────────┐
│ je │
4 ├───────────────────┤
│ S │
8 ├───────────────────┤
│ L │
│ │
16 └───────────────────
Maintenant , si vous avez eu trois variables locales dans une fonction, des types RefType
, ValType
et int[]
, comme celui - ci:
RefType refType;
ValType valType;
int[] intArray;
alors votre pile pourrait ressembler à ceci:
0 ┌───────────────────┐
│ refType │
4 ├───────────────────┤
│ valType │
│ │
│ │
│ │
20 ├───────────────────┤
│ intArray │
24 └───────────────────
Si vous avez attribué des valeurs à ces variables locales, comme ceci:
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;
Ensuite, votre pile pourrait ressembler à ceci:
0 ┌───────────────────┐
│ 0x4A963B68 │ - adresse de tas de `refType`
4 ├───────────────────┤
│ 200 │ - valeur de `valType.I`
│ 0x4A984C10 │ - adresse de tas de `valType.S`
│ 0x44556677 │ - bas 32 bits de `valType.L`
│ 0x00112233 │ - 32 bits de haut de `valType.L`
20 ├───────────────────┤
│ 0x4AA4C288 │ - adresse de tas de `intArray`
24 └───────────────────
La mémoire à l'adresse 0x4A963B68
(valeur de refType
) serait quelque chose comme:
0 ┌───────────────────┐
│ 100 │ - valeur de `refType.I`
4 ├───────────────────┤
│ 0x4A984D88 │ - adresse de tas de `refType.S`
8 ├───────────────────┤
│ 0x89ABCDEF │ - 32 bits bas de `refType.L`
│ 0x01234567 │ - 32 bits de haut de `refType.L`
16 └───────────────────
La mémoire à l'adresse 0x4AA4C288
(valeur de intArray
) serait quelque chose comme:
0 ┌───────────────────┐
│ 4 │ - longueur du tableau
4 ├───────────────────┤
│ 300 │ - `intArray [0]`
8 ├───────────────────┤
│ 301 │ - `intArray [1]`
12 ├───────────────────
│ 302 │ - `intArray [2]`
16 ├───────────────────
│ 303 │ - `intArray [3]`
20 └───────────────────┘
Maintenant, si vous passiez intArray
à une autre fonction, la valeur poussée sur la pile serait 0x4AA4C288
, l'adresse du tableau, pas une copie du tableau.