代码如下,写出最后的输出结果 public class Teacher
{ public string name; public Teacher(string name)
{ this.name=name; }
public static void Main()
{ Teacher tea = new Teacher("ACCP3.0"); Teacher teaNew =new Teacher("ACCP4.0"); tea =teaNew; teaNew.name = "ACCP5.0"; Console.WriteLine(tea.name); Console.WriteLine(teaNew.name); teaNew = null; if(tea!=null) Console.WriteLine(tea.name);
}
}我在vs2005中测试过了,输出结果是
ACCP5.0
ACCP5.0
ACCP5.0前两个输出好理解,C#中对象是引用类型,对应同一块内存空间,可以做到同步更新。
问题是既然是引用类型,那么
teaNew = null;
的时候
tea 没有同步设置成null呢,
求解释?????????????????????
{ public string name; public Teacher(string name)
{ this.name=name; }
public static void Main()
{ Teacher tea = new Teacher("ACCP3.0"); Teacher teaNew =new Teacher("ACCP4.0"); tea =teaNew; teaNew.name = "ACCP5.0"; Console.WriteLine(tea.name); Console.WriteLine(teaNew.name); teaNew = null; if(tea!=null) Console.WriteLine(tea.name);
}
}我在vs2005中测试过了,输出结果是
ACCP5.0
ACCP5.0
ACCP5.0前两个输出好理解,C#中对象是引用类型,对应同一块内存空间,可以做到同步更新。
问题是既然是引用类型,那么
teaNew = null;
的时候
tea 没有同步设置成null呢,
求解释?????????????????????
对象浅拷贝,只是复制本身,它包含的对象只是复制引用
拷贝完毕后,源对象和拷贝对象的字段会引用同一个值
if(tea.name!=null) Console.WriteLine(tea.name);
这样估计就行了吧
teaNew拿了个纸条上写着“花园路5号”,你访问teaNew就能找到张三
同样,
tea把teaNew手里的纸条抄了一份,上面也写着“花园路5号”,你访问tea也能找到张三这时,你把teaNew手里的纸条上的字擦掉,你再问teaNew,他就不知道张三在那住了
但是不影响tea啊,因为他手里的纸条还写着张三家的地址:“花园路5号”所以你还能通过tea找到张三没看晕吧!!!
就是说你这个只是一个值的重新赋值,等于说就是把teaNew赋给了tea,而不是把tea的值指向teaNew的值的内存块,所以这里才会有那样的输出.
而teaNew=null只是让teaNew丢失了对对象的引用,相当于teaNew失恋了,而tea对那个对象的引用依然没有变,那个对象本身也没有变.所以这时候 所以问teaNew你女朋友的名字叫什么,他会生气(抛出异常),而问tea的话他还是会说她叫ACCP5.0
Console.WriteLine(tea.name);//3.0 Teacher teaNew = new Teacher("ACCP4.0");
Console.WriteLine(teaNew.name);//4.0 tea = teaNew;
Console.WriteLine(tea.name);//4.0 teaNew.name = "ACCP5.0"; Console.WriteLine(tea.name);//5.0 Console.WriteLine(teaNew.name);//5.0 teaNew = null;
// Console.WriteLine(teaNew.name);//内存会报错 if (tea != null)//true Console.WriteLine(tea.name);//5.0
之后全部都是5.0
对象浅拷贝,只是复制本身,它包含的对象只是复制引用
拷贝完毕后,源对象和拷贝对象的字段会引用同一个值
有道理
UP!!!
Teacher tea;
的時候,并沒有在內存中真的創建對象,而只是聲明了Teacher類型的引用變量Tea。該變量可能會指向一個Teacher對象,但目前還沒有,它的值為null。
new Teacher("ACCP3.0");
的時候才真正的在內存中創建了一個新的Teacher對象。
連在一起:Teacher tea = new Teacher("ACCP3.0");
才是將物理內存地址與變量tea關聯起來。這裡我就不畫圖,從網上找來幾張圖,請自動舉一反三,將就著看吧。這裡將Tea看成那條線y,可以這樣理解:“引用變量tea維護一個Teacher(圖中的Student)對象的句柄”。
同樣Teacher teaNew =new Teacher("ACCP4.0");可以理解成:”引用變量teaNew維護一個Teacher(圖中的Student)對象的句柄“(看圖時將x忽略掉。)
到目前為止,tea和teaNew還是各自系著自己的氣球對不對?繼續往下分析:
tea =teaNew;
這句可以理解成tea這條繩子放棄了自己的球,去連teaNew的氣球。這樣氣球一(new Teacher("ACCP3.0"))在內存中漂著,沒繩子在抓住它,氣球二(new Teacher("ACCP4.0"))則有兩條繩子牽著。
如下圖:teaNew.name = "ACCP5.0";
繩子還是那個繩子,氣球還是那個氣球,只是氣球二的name值改成了"ACCP5.0".teaNew = null;
表示,teaNew放棄了氣球二,teaNew這條繩子現在沒系住任何一個氣球。if(tea!=null)
Console.WriteLine(tea.name);
但tea這條繩子還系在氣球二上啊,所以還是會輸出ACCP5.0
18楼说的很对,跟什么拷贝没什么关系.
开始时,tea =teaNew; 使得他们俩都指向新建的teaNew的内存,然后对他们的操作,其实是对同一内存对象的修改,所以显示一样.然后让teaNew=null 只是使teaNew指针指向为NULL ,此时tea指向的还是原来的内存,所以不会改变.
tea变量里存的对象的地址, 比如 地址 123456677
那么 teateaNew也是一样的,当teaNew赋值为 null的时候呢,
teaNew就没有保存任何地址,而这时的tea仍然保存123456677地址,而这个地址就是你new的对象的地址。因此,tea对象的内容没有改变
tea =teaNew; 复制引用,相当于复制指针地址teaNew = null; 清空teaNew的引用
但是内存块中的数据并没有清空,tea还是引用这个内存块中的数据,所以输出的还是ACCP5.0
首先 techNew只是一个引用 只是将 techNew的引用地址值赋成空
techer那个引用还是指向那块数据,所以里面内容没有改变。
赋值的是内存空间 或者说 让两个对象指向一块内存空间
其中一个修改了 所有指向该空间的对象都修改了
但是当其中一个对象=null的时候 只是让这个对象不再指向这个内存空间
但是这个内存空间仍有其他对象引用 所以不会被回收 其他指向该空间的对象照常使用 没有影响~~
犯得上画个图吗 浪费地方~
teaNew本身是两个引用,而你new出来的是它们指向的内容
tea=new只是把tea本身设成不指向任何对象,也就是说,只修改了tea本身,而不是tea指向的对象。
而teaNew仍然指向原来的对象,自然不会null
这句话只是将teaNew的引用清空,但是并没有将tea的引用清空
对象浅拷贝,只是复制本身,它包含的对象只是复制引用
拷贝完毕后,源对象和拷贝对象的字段会引用同一个值
要不然你改某个成员,然后通过其他的引用去访问这个成员的时候,怎么会得到的都是最后一次修改的结果呢。
这说明所有的对象引用都引用了同一个对象(按C的说法其实这就是指针,只是高级语言把它屏蔽掉了,让你感觉不到而已,实质上就是指针)。
再举一个例子
C++中 假定有个class 是 Stu你可以 这样: Stu stu,
你还可以这样:Stu *pstu = new Stu();
这下清楚了吧 new返回的实际只是对象的地址而已。
但是!!C#中通过它自己的方式:定义所有对象传递全部是引用传递,它使得只要是对象那就肯定在堆中,你就是说 你只能通过new来创建对象 ,而C++ 存在栈中对象,即不使用new开辟堆内存