C#中使用同一变量名多次实例化类时内存会发生什么变化
相同变量名重复实例化类对象的内存相关问题解答
示例代码如下:
for (int i = 0; i < 4; i++) { Person person1 = new Person(); }
- 重复实例化时的内存变化
Person属于引用类型,运行时的存储分为两部分:对象实例本身存在托管堆上,栈上的person1变量只存储堆上实例的内存地址。
每次循环迭代时,new Person()会先在堆上申请内存创建新的Person实例,再把新实例的地址赋值给当前迭代作用域内的person1变量。当前迭代结束后,person1会超出作用域失效,之前关联的堆实例就会失去有效引用,成为垃圾对象等待*垃圾回收器(GC)*清理。 - 第二次创建对象能否复用第一次的内存地址
默认逻辑下不会主动复用第一次的内存地址。如果第一次创建的实例还没被GC回收,对应的内存地址属于被占用状态,肯定无法复用;就算之前的实例已经被GC回收释放了地址,.NET的内存分配器也不会优先复用刚释放的地址,只有在GC执行内存压缩整理、或者内存分配时刚好命中空闲地址块的极端巧合下才可能出现地址相同的情况,这属于运行时底层的偶发行为,不是开发层面的主动复用。 - 第二次创建对象是否会分配新的地址
只要执行new关键字实例化引用类型,运行时一定会在堆上分配新的内存空间,返回全新的内存地址。除非你手动实现对象池复用已创建的对象、不执行new操作,否则每次new出来的实例都会对应独立的新内存地址。
四次循环的内存变化参考:
- 第1次迭代
栈(Stack):当前作用域的person1→ 存储堆地址0x10001
堆(Heap):地址0x10001存储第1个Person实例的所有数据
迭代结束:person1超出作用域失效,0x10001的实例失去引用,标记为可回收- 第2次迭代
栈(Stack):新迭代作用域的person1→ 存储堆地址0x10032
堆(Heap):地址0x10032存储第2个Person实例的所有数据
迭代结束:person1超出作用域失效,0x10032的实例失去引用,标记为可回收
第3、4次迭代逻辑和上述完全一致,每次都会生成新的堆内存地址
内容的提问来源于stack exchange,提问作者coder
相关产品推荐
相关产品推荐

