A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 杨恩锋 黑马帝   /  2011-10-26 11:06  /  3284 人查看  /  14 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

我们都知道string是引用类型来的,那么下面代码为什么输出结果为”abc“,按道理说引用的话就应该输出结果为”efg“。
  1. string s1="abc";
  2. string s2=s1;
  3. s1="efg";
  4. Console.WriteLine(s2);
复制代码

14 个回复

倒序浏览
本帖最后由 黄朝辉 于 2011-10-26 14:09 编辑

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

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

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

评分

参与人数 1技术分 +1 收起 理由
官方工作人员 + 1 加油加油

查看全部评分

回复 使用道具 举报
无论你怎么改变s1的值,s2指向的是s1原来的内存的地址,内存中的值是不改变的,所以我们得到的是内存中的值,而不是所谓的s1,这是内存的值的读取!!!
回复 使用道具 举报
从我学C++的经验来看,既然C#是从C++发展来的,肯定和C++中的string类似,c#没有指针,但是它肯定和java一样底层封装了指针,而c++中的string的对象引用指向的是一样常量内存地址,而且在函数中传值的时候传递的是拷贝,而非内存地址,所以它会调用复制构造函数将实参中的值复制一份给形参。
回复 使用道具 举报
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:52
7#
哥们研究得很深啊,学习了,谢谢
回复 使用道具 举报
章坚 黑马帝 2011-10-27 11:37:01
8#
STRING 是引用类型哦
回复 使用道具 举报
陈涛 黑马帝 2011-10-31 23:22:43
9#
用简单的一句话来说就是, s2是指向"s1指向的值"
回复 使用道具 举报
郑文 黑马帝 2011-11-1 14:59:45
10#
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"这个字符串存储在堆区的. 也就是说栈区的值可以改变,堆区的值不能变. 你可以试一试与数组的比较.

评分

参与人数 1技术分 +1 收起 理由
杨恩锋 + 1

查看全部评分

回复 使用道具 举报
我发现我第一次回答不正确,因为昨天晚上看了一本书后发现楼主所说的之所以输出abc
是运算符重载的关系。
回复 使用道具 举报
10642491 黑马帝 2011-11-3 09:04:10
12#
黄朝辉 发表于 2011-11-3 08:57
我发现我第一次回答不正确,因为昨天晚上看了一本书后发现楼主所说的之所以输出abc
是运算符重载的关系。 ...

求详解,那MSIL代码证明是重载吗?
回复 使用道具 举报
郑文 黑马帝 2011-11-4 13:52:36
13#
不是重载 就是内存分配的问题。
回复 使用道具 举报
为了提高性能和保证执行效率,.NET Framework维护了一个字符串池,也称为“暂存池”或“常量池”,用以对使用过的字符串进行缓存。所以s2的值并没有改变
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马