黑马程序员技术交流社区

标题: string不是引用类型的嘛? [打印本页]

作者: 杨恩锋    时间: 2011-10-26 11:06
标题: string不是引用类型的嘛?
我们都知道string是引用类型来的,那么下面代码为什么输出结果为”abc“,按道理说引用的话就应该输出结果为”efg“。
  1. string s1="abc";
  2. string s2=s1;
  3. s1="efg";
  4. Console.WriteLine(s2);
复制代码

作者: 黄朝辉    时间: 2011-10-26 14:00
本帖最后由 黄朝辉 于 2011-10-26 14:09 编辑

String是一个很特殊的类型,和普通引用类型不一样,是一种不可变类型。简单说,就是每个字符串都占据着一部分内存地址,并且它的值是不可改变的。当给String s1赋值的时候,它并没有改变原来s1指向的字符串的值,而是将s1指向了另一个字符串所在的位置。这次赋值之后,s1和s2所引用的对象已经不同了,查看它们的内存地址可以确认这一点。
作者: 李荣壮    时间: 2011-10-26 14:33
本帖最后由 李荣壮 于 2011-10-26 14:35 编辑

引用类型在内存中 需要两块地方 储存数据:堆和栈
数据存储在堆中,而引用存储在栈中(也就是存储的堆的地址).
你每次对它赋值以后,都会重新在内存中创建一个堆.栈中将存储 新的堆的地址
所以当执行 s1="efg"; 时 s1引用到新的内存地址,而s2还是指向原来的内存地址.

我们通过下面的代码试一下
  1. //string.ReferenceEquals 用于判断指定的两个Object类型是否为相同实例
  2. Console.WriteLine(string.ReferenceEquals(s1, s2));
复制代码

作者: 何荣智    时间: 2011-10-26 14:41
无论你怎么改变s1的值,s2指向的是s1原来的内存的地址,内存中的值是不改变的,所以我们得到的是内存中的值,而不是所谓的s1,这是内存的值的读取!!!
作者: 10642491    时间: 2011-10-26 21:44
从我学C++的经验来看,既然C#是从C++发展来的,肯定和C++中的string类似,c#没有指针,但是它肯定和java一样底层封装了指针,而c++中的string的对象引用指向的是一样常量内存地址,而且在函数中传值的时候传递的是拷贝,而非内存地址,所以它会调用复制构造函数将实参中的值复制一份给形参。
作者: 李荣壮    时间: 2011-10-26 22:16
10642491 发表于 2011-10-26 21:44
从我学C++的经验来看,既然C#是从C++发展来的,肯定和C++中的string类似,c#没有指针,但是它肯定和java一 ...

C#中的string与C++中是不一样的,C++中string的实质是char数组,而C#中将string实质为对象,继承自Object类
作者: 10642491    时间: 2011-10-27 07:23
哥们研究得很深啊,学习了,谢谢
作者: 章坚    时间: 2011-10-27 11:37
STRING 是引用类型哦
作者: 陈涛    时间: 2011-10-31 23:22
用简单的一句话来说就是, s2是指向"s1指向的值"
作者: 郑文    时间: 2011-11-1 14:59
C#中的字符串有个特性是字符串不可变性,字符串的值是存储到堆区,也就是说字符串一旦复制也就无法改变其值,string s1= "abc";string s2=s1 ; 意思是S2的指向s1的内存空间。当s1改变时 也就是s1="efg";  其实是又开辟了内存空间来存储 "efg"此时s1存的是"efg"的地址。而“abc”的值并被覆盖,s2仍然存储的"abc"的地址。只是s1无法访问"abc"了
“abc”的值实际还有,并没有被"efg"覆盖.这里要区分 s1实际的值 和地址的感念 。 例如 string s1 =  "abc"; s1存储的是 “abc”值的地址 存储在栈区, "abc"这个字符串存储在堆区的. 也就是说栈区的值可以改变,堆区的值不能变. 你可以试一试与数组的比较.
作者: 黄朝辉    时间: 2011-11-3 08:57
我发现我第一次回答不正确,因为昨天晚上看了一本书后发现楼主所说的之所以输出abc
是运算符重载的关系。
作者: 10642491    时间: 2011-11-3 09:04
黄朝辉 发表于 2011-11-3 08:57
我发现我第一次回答不正确,因为昨天晚上看了一本书后发现楼主所说的之所以输出abc
是运算符重载的关系。 ...

求详解,那MSIL代码证明是重载吗?
作者: 郑文    时间: 2011-11-4 13:52
不是重载 就是内存分配的问题。
作者: 王金凤    时间: 2011-11-4 16:11
为了提高性能和保证执行效率,.NET Framework维护了一个字符串池,也称为“暂存池”或“常量池”,用以对使用过的字符串进行缓存。所以s2的值并没有改变




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2