int[] myIntegers; myIntegers = new int[100]; 在上面的代码中,是否是new int [100]在堆上生成数组?根据我通过c#进行的CLR阅读,答案是肯定的。但是我不明白的是,数组内部的实际int发生了什么。因为它们是值类型,所以我猜想它们必须装箱,例如,我可以将myIntegers传递给程序的其他部分,如果一直将它们留在程序中,则会使堆栈混乱。还是我错了?我猜想它们只会被装箱,并且只要数组存在就可以在堆中生存。问题来源于stack overflow
您的数组分配在堆上,并且没有将int装箱。
造成混淆的原因很可能是因为人们曾说过,引用类型是在堆上分配的,而值类型是在堆栈上分配的。这不是一个完全准确的表示。
所有局部变量和参数都分配在堆栈上。这包括值类型和引用类型。两者之间的区别仅在于变量中存储的内容。毫不奇怪,对于值类型,该类型的值直接存储在变量中,对于引用类型,该类型的值存储在堆中,对此值的引用就是存储在变量中的值。
字段也是如此。当为聚合类型(a class或a struct)的实例分配内存时,它必须包括其每个实例字段的存储。对于引用类型字段,此存储仅保存对该值的引用,该引用本身将在以后分配给堆。对于值类型字段,此存储保存实际值。
因此,给定以下类型:
class RefType{ public int I; public string S; public long L; }
struct ValType{ public int I; public string S; public long L; } 这些类型中的每一个的值都将需要16个字节的内存(假设字大小为32位)。字段I在每种情况下需要4个字节来存储其值,则场S需要4个字节来存储其引用,字段L需要8个字节存储其值。因此,对于两者的价值存储RefType和ValType看起来像这样:
0┌──────────────┐ │我│ 4├─────────────┤ │S│ 8├──────────────┤ │L│ ││ 16└──────────────┘ 现在,如果你在一个函数中有三个局部变量,类型RefType,ValType和int[],就像这样:
RefType refType; ValType valType; int[] intArray; 那么您的堆栈可能看起来像这样:
0┌──────────────┐ │引用类型│ 4├─────────────┤ │valType│ ││ ││ ││ 20├──────────────┤ │intArray│ 24└──────────────┘ 如果您为这些局部变量分配了值,如下所示:
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; 然后您的堆栈可能看起来像这样:
0┌──────────────┐ │0x4A963B68│-refType
的堆地址 4├─────────────┤ │200│-valType.I的值 │0x4A984C10│-valType.S
的堆地址 │0x44556677│-valType.L
的低32位 │0x00112233│-valType.L
的高32位 20├──────────────┤ │0x4AA4C288│-intArray
的堆地址 24└──────────────┘ 地址处的内存0x4A963B68(值为refType)将类似于:
0┌──────────────┐ │100│-refType.I
的值 4├─────────────┤ │0x4A984D88│-refType.S
的堆地址 8├──────────────┤ │0x89ABCDEF│-refType.L
的低32位 │0x01234567│-refType.L
的高32位 16└──────────────┘ 地址处的内存0x4AA4C288(值为intArray)将类似于:
0┌──────────────┐ │4│-数组长度 4├─────────────┤ │300│-intArray [0]
8├──────────────┤ │301│-intArray [1]
12├──────────────┤ │302│-intArray [2]
16├─────────────┤ │303│-intArray [3]
20└──────────────┘ 现在,如果您传递intArray给另一个函数,则压入堆栈的值将是0x4AA4C288数组的地址,而不是数组的副本。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。