Array Anda dialokasikan pada heap, dan int tidak kotak.
Sumber kebingungan Anda kemungkinan karena orang mengatakan bahwa tipe referensi dialokasikan pada heap, dan tipe nilai dialokasikan pada tumpukan. Ini bukan representasi yang sepenuhnya akurat.
Semua variabel dan parameter lokal dialokasikan pada tumpukan. Ini termasuk tipe nilai dan tipe referensi. Perbedaan antara keduanya hanyalah apa yang disimpan dalam variabel. Tidak mengherankan, untuk tipe nilai, nilai tipe disimpan langsung dalam variabel, dan untuk tipe referensi, nilai tipe disimpan di heap, dan referensi ke nilai ini adalah apa yang disimpan dalam variabel.
Hal yang sama berlaku untuk bidang. Ketika memori dialokasikan untuk instance dari tipe agregat (a class
atau astruct
), itu harus menyertakan penyimpanan untuk masing-masing bidang instance. Untuk bidang tipe referensi, penyimpanan ini hanya menyimpan referensi ke nilai, yang akan dialokasikan pada tumpukan nanti. Untuk bidang tipe nilai, penyimpanan ini menyimpan nilai aktual.
Jadi, diberikan jenis berikut:
class RefType{
public int I;
public string S;
public long L;
}
struct ValType{
public int I;
public string S;
public long L;
}
Nilai dari masing-masing jenis ini akan membutuhkan 16 byte memori (dengan asumsi ukuran kata 32-bit). Bidang I
dalam setiap kasus membutuhkan 4 byte untuk menyimpan nilainya, bidang S
membutuhkan 4 byte untuk menyimpan referensi, dan bidang L
membutuhkan 8 byte untuk menyimpan nilainya. Jadi memori untuk nilai keduanya RefType
dan ValType
terlihat seperti ini:
0 ┌──────────────────┐
│ I │
4 ├──────────────────┤
│ S │
8 ├──────────────────┤
│ L │
│ │
16 └──────────────────┘
Sekarang jika Anda memiliki tiga variabel lokal dalam suatu fungsi, jenis RefType
, ValType
dan int[]
, seperti ini:
RefType refType;
ValType valType;
int[] intArray;
maka tumpukan Anda mungkin terlihat seperti ini:
0 ┌──────────────────┐
│ refType │
4 ├──────────────────┤
│ valType │
│ │
│ │
│ │
20 ├──────────────────┤
│ intArray │
24 └──────────────────┘
Jika Anda menetapkan nilai ke variabel lokal ini, seperti:
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;
Maka tumpukan Anda mungkin terlihat seperti ini:
0 ┌──────────────────┐
│ 0x4A963B68 │ - heap address `refType`
4 ├──────────────────┤
│ 200 │ - nilai `valType.I`
│ 0x4A984C10 │ - tumpukan alamat `valType.S`
│ 0x44556677 │ - `valType.L` 32-bit yang rendah
│ 0x00112233 │ - `valType.L` 32-bit yang tinggi
20 ├──────────────────┤
│ 0x4AA4C288 │ - heap address `intArray`
24 └──────────────────┘
Memori di alamat 0x4A963B68
(nilai refType
) akan menjadi seperti:
0 ┌──────────────────┐
│ 100 │ - nilai `refType.I`
4 ├──────────────────┤
│ 0x4A984D88 │ - heap address `refType.S`
8 ├──────────────────┤
│ 0x89ABCDEF │ - `refType.L` 32-bit yang rendah
│ 0x01234567 │ - `refType.L` 32-bit yang tinggi
16 └──────────────────┘
Memori di alamat 0x4AA4C288
(nilai intArray
) akan menjadi seperti:
0 ┌──────────────────┐
│ 4 │ - panjang array
4 ├──────────────────┤
│ 300 │ - `intArray [0]`
8 ├──────────────────┤
│ 301 │ - `intArray [1]`
12 ├──────────────────┤
│ 302 │ - `intArray [2]`
16 ├──────────────────┤
│ 303 │ - `intArray [3]`
20 └──────────────────┘
Sekarang, jika Anda beralih intArray
ke fungsi lain, nilai yang didorong ke stack akan menjadi 0x4AA4C288
, alamat array, bukan salinan array.