开发者社区> 问答> 正文

数组,堆和堆栈以及值类型

int[] myIntegers; myIntegers = new int[100]; 在上面的代码中,是否是new int [100]在堆上生成数组?根据我通过c#进行的CLR阅读,答案是肯定的。但是我不明白的是,数组内部的实际int发生了什么。因为它们是值类型,所以我猜想它们必须装箱,例如,我可以将myIntegers传递给程序的其他部分,如果一直将它们留在程序中,则会使堆栈混乱。还是我错了?我猜想它们只会被装箱,并且只要数组存在就可以在堆中生存。问题来源于stack overflow

展开
收起
保持可爱mmm 2020-02-07 01:15:29 343 0
1 条回答
写回答
取消 提交回答
  • 您的数组分配在堆上,并且没有将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数组的地址,而不是数组的副本。

    2020-02-07 01:15:46
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载