int的一点事,读《深入C#内存管理来分析值类型&引用类型,装箱&拆箱,堆栈几个概念组合之间的区别》

今天稍有点空闲,本来想看看网页啥的,无奈老板坐镇,只好翻开《CLR VIA C#》

有些地方有点迷糊,准备敲代码试一下,打开学习用的项目,突然发现有个以前看《深入C#内存管理来分析值类型&引用类型,装箱&拆箱,堆栈几个概念组合之间的区别》遗留下来的问题

代码是这样子的

             int i = 4;
             object o = i;
             object o2 = o;
             Console.WriteLine(ReferenceEquals(o, o2)); //true
             o = 8;
             Console.WriteLine(ReferenceEquals(o, o2)); //false
 
             Console.WriteLine("i={0}, o={1}, o2={2}", i, o, o2); //4, 8, 4, why?

 

结果原帖子里也有,但是为什么,不太明白,只是知道和装箱有点关系(int转成object当然要装箱)。查引用,上面代码第4行,说明两个指向的是同一个对象,但o=8之后,两个就不是同一个对象了。这是为啥?

无奈祭出ILDASM,这回现形了(略去Console.WriteLine之类的代码) 

IL_0001:  ldc.i4.4
   IL_0002:  stloc.0
   IL_0003:  ldloc.0
   IL_0004:  box        [mscorlib]System.Int32
   IL_0009:  stloc.1
   IL_000a:  ldloc.1
   IL_000b:  stloc.2
   IL_000c:  ldc.i4.8
   IL_000d:  box        [mscorlib]System.Int32
   IL_0012:  stloc.1

 

1. 创建一个常数,值为4,入栈

2. 出栈,将值放入第一个内存变量(int i = 4)

3. 将第一个内存变量入栈

4. 装箱(object o = i)

5. 出栈,将o的地址放入第二个内存变量

6. 将第二个内存变量入栈

7. 出栈,将地址放入第三个内存变量(o的地址)(object o2 = o)

8. 创建一个常数,值为8,入栈

9. 装箱

10. 出栈,将装箱后的地址放入第二个内存变量(o = 8)

这样看来就比较清楚了,o2和o的地址明显不一样,因为o=8中有一个对8的装箱操作,之后仅修改了第二个内存变量中保存的地址,而第三个内存变量中保存的仍然是上次装箱4时的地址,所以o=8, o2=4

顺便说一下string吧

string是不可变的,也就是说,一个string对象创建以后,如果修改它的内容,就会创建一个新的string对象,换句话说,地址变了。《CLR VIA C#》中的解释是string pooling,所有内容相同的字符串对象都会指向同一个metadata中的同一个string对象。所以下面的这段代码

String s1 = "Hello";
String s2 = "Hello";
Console.WriteLine(Object.ReferenceEquals(s1, s2));

结果是True
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值