值类型与引用类型初窥
2010-11-26 13:32 Shawn.Cheng 阅读(148) 评论(0) 编辑 收藏 举报没有时间写废话,直接上测试代码。
class TestAddressRef
{
public int num;
}
class Program
{
static void Main(string[] args)
{
TestAddressRef tar1=new TestAddressRef();
tar1.num = 1;
TestAddressRef tar2 = tar1;
TestAddressRef tar3=new TestAddressRef();
TestAddressRef tar4 = tar3;
tar3.num = 3;
tar3 = tar1;
Console.WriteLine("tar1的值{0}/ntar2的值{1}/ntar3的值{2}/ntar4的值{3}/n", tar1.num, tar2.num, tar3.num,tar4.num);
}
输出为:
tar1的值1
tar2的值1
tar3的值1
tar4的值3
我是这样理解的:
new 一个对像后,在堆内分配一个该对象的存储空间。在栈内为该标志符赋值为 堆内该对象的首地址,并记录对象类型(空间什么的)。
如这句话TestAddressRef tar1=new TestAddressRef();
而对于TestAddressRef tar2;相当于仅在栈内分配了一个空间,保存实际对象的地址为null(即该对象未在队内分配空间)。当有 tar2 = tar1时,将tar1栈内的值给了tar2,这样,tar2也指向了与1相同的堆内对象。
3 和4 就比较有意思了,3申请了新空间后,4也得到这个地址,然后3栈内保存的地址又被1赋值,即3有指向了1所指向的堆空间,也就是放弃了原来申请的堆空间的控制(4控制着该堆内的对象,4这里起到了捕获3遗漏空间的作用)。就出现了如上结果。
我有个疑问,当tar3 放弃了对原堆空间的控制后,转向1,会不会产生内存泄露了呢(不用4捕获的情况下)???
因为编译器无法获知原来tar3申请的空间什么时候会失效(其实,如果不是我们用tar4来捕获,到最后tar4超出了它的作用域,连我们自己也不知道该空间内保存的值什么时候才会不被用到),编译器貌似就难以在适时的时候进行垃圾回收了!????我暂时还没想明白,应该牵涉到垃圾回收的机制吧,等我想明白了再来补上。
恩,就这样。
欢迎提出不同的观点。
###
补1:
(1) 不是所有new一下就是引用类型,如struct类型。
定义个结构类型Mystruct, 如果写Mystruct ms=new Mystruct();结构实例对象仍然是在栈内分配的。new一下,编译器会认为实例已初始化。如果没有new,认为实例的所有字段没有初始化,不可访问使用,编译错误。
#####2011-10-12
或许我们根本不用担心这个问题,C#垃圾回收应该就是干这个事的。至于什么时候才回收,现在暂时还不是很清楚。