同一作用域内相同名称多次创建数组的内存地址变化问题
C#中两次执行
new T[size]为同一数组变量赋值的内存行为说明 核心结论
- 两次执行
new T[size]赋值操作时,会触发全新的托管堆内存分配,数组变量arr存储的内存起始地址会发生变化 - 不存在原地扩容的逻辑,原有数组的数据也不会自动拷贝到新分配的内存空间
- 原数组内存如果没有其他引用指向,会被后续垃圾回收机制自动回收
原理说明
C#中数组属于引用类型:
- 局部数组变量
arr本身存储在栈内存中,存储的实际内容是托管堆上数组对象的首地址 - 第一次执行
arr = new byte[6]时,CLR会在托管堆上分配对应大小的内存,将该内存的首地址赋值给栈上的arr变量 - 第二次执行
arr = new byte[10]时,CLR会重新在托管堆申请足够存储10个byte的全新内存块,将新的内存首地址覆盖到arr变量中,此时arr和原来的6长度数组没有任何关联
注意:你所说的「原地扩容、自动拷贝数据」是
List<T>等封装集合的内部实现逻辑,原生数组的长度在创建后就是固定的,没有内置扩容能力,List<T>的扩容本质也是内部执行new T[newSize]再手动拷贝旧数据的逻辑,并不是真的原地扩容。
示例代码运行验证
你提供的代码本身就可以验证上述结论:
using System; class HelloWorld { static void Main () { byte[] arr; arr = new byte[6]; arr[2] = 6; Console.WriteLine ("len = {0}\n{1}", arr.Length, arr[2]); arr = new byte[10]; arr[2] = 10; Console.WriteLine ("len = {0}\n{1}", arr.Length, arr[2]); } }
运行输出如下:
len = 6 6 len = 10 10
从输出可以看到,第二次赋值后arr[2]没有保留第一次设置的6,说明并没有发生旧数据拷贝的操作,arr已经指向了全新的数组对象。
内容的提问来源于stack exchange,提问作者Abdullah
相关产品推荐
相关产品推荐

