Swift中Array运行时内存重分配机制及相关内存问题咨询
C#数组扩容与内存分配的核心细节
1. 栈与堆的分工:数组结构体 vs 元素存储
先澄清一个容易搞混的点:虽然Array是值类型结构体,但栈上只存数组的"管理信息结构体"——里面包含指向实际元素存储区的指针、数组长度、维度这些元数据。真正的元素数据,不管是什么类型,全存在托管堆上。这就是栈内存固定却能扩容的关键:扩容操作根本不涉及栈的修改,只在堆上操作。
2. 运行时扩容的实际操作
当你执行数组扩容(比如调用Array.Resize)时,背后的流程是:
- 确定新的容量(一般是原容量的1.5到2倍,具体倍数看CLR实现)
- 在托管堆上分配一块对应新容量的内存块
- 把旧数组堆内存里的所有元素复制到新块里
- 更新栈上(或其他地方)的数组结构体,让它的指针指向新的堆内存
- 旧的堆内存块因为没人引用了,会被垃圾回收器在合适的时候清理掉
3. 存储引用类型元素的内存情况
如果数组存的是引用类型(比如string、自定义类的实例),数组的堆存储区里每个元素都是一个引用指针(32位系统占4字节,64位占8字节)。这些指针本身要占用内存,它们指向各自对象实例所在的托管堆区域——简单说,数组存的是"对象的地址",不是对象本身。
4. 存储值类型元素的内存情况
如果数组元素是值类型(比如int、自定义struct),数组的堆存储区里直接存的是值类型的完整实例,所有元素连续排列,不需要额外的引用指针。比如int[]数组,堆上就是一串连续的4字节整数,没有多余的内存开销。
内容的提问来源于stack exchange,提问作者Alisher Baigazin
相关产品推荐
相关产品推荐

