posted on 2004-08-30 09:04 鞠强 阅读(3040) 评论(29) 编辑 收藏 所属分类: .NET CLR研究
string s1 = "hello"; string s2 = s1; 假设此时s2指向的地址为A1,因为“s1被修改后,会重新分配一块内存”,假设新分配的内存地址为A2。注意此时s2指向的仍然是A1,当然输出时s2的值还是“hello”了。 回复 引用 查看
to 宽带鱼,我困惑的是,“s1被修改后,会重新分配一块内存”。CLR为什么要这么处理?这个和reference相违背吧? 回复 引用 查看
看汇编代码,对于s2 = s1,是这样的: 对于s1 = "hello",是这样的: string s2 = s1; 00000017 mov edi,esi s1 = "你好"; 0000006d mov eax,dword ptr ds:[01DC0078h] 00000073 mov esi,eax 注意上面的dword ptr,很明显,CLR把ds:[01DC0078h]的偏移作为了esi的新位置。但是,为什么对s1改变值的时候,CLR要这么做?要分配一块新的内存? 回复 引用 查看
In .Net as well as Java, we cannot modify a string value. Everytime we attempt a string value, actuall another string is created. In other words, when we assign s1="world". The original string "hello" has not been touched. Instead, a new string "world" is created and s1 now points to the new string. Keep in mind, string is immutable. 回复 引用 查看
string是简单数据类型的类,与普通的类的处理方式上不太一样 回复 引用
s1="hello"这样的语句,它的操作是在堆中创建了一个String类型的对象,然后呢,将这个对象的地址赋给s1。接着,如果使用了s2=s1这样的语句,等于是将"hello"对象的地址也赋给了s2。而到了最后,s1="world"的语句实质上并不会去改变"hello"这个对象,它改变的是s1指向的地址,而不是它原来指向对象的内容。 回复 引用 查看
您下面给出的那个例子跟String的例子并没有可比性,因为下面的例子并没有出现改变引用本身的语句,因为s1="world"不等同于t1.Number=20,而是等同与t1=new Test();t1.Number=20。 回复 引用 查看
to fantasysoft,我明白了!最后的s1 = "world",相当于是s1 = new string("world");已经是一个新的实例了,呵呵。谢谢!!! 回复 引用 查看
楼主看看这几个: http://blog.joycode.com/qqchen/archive/2004/08/21/31216.aspx http://blog.joycode.com/qqchen/archive/2004/08/21/31217.aspx http://blog.joycode.com/qqchen/archive/2004/08/23/31344.aspx 回复 引用 查看
谢谢楼上几位的解释:) 回复 引用 查看
多谢sumtec的指点! 回复 引用 查看
sumtec贴的qqchen写的这篇,以及jgtm(mvp)的回复,我认为基本上把string问题解释清楚了。 代码我也运行了,大家如有兴趣,自己run一下看看!而且,我自己在其中作了一点改动,增加了一个:string s = string.Intern("Hello");其实看这句就知道了。 static unsafe void ModifyConst() { string str = "Hello"; fixed(char* pstr = str) { pstr[0] = 'X'; } } static void Test2() { ModifyConst(); StringBuilder sb = new StringBuilder("Hel"); sb.Append("lo"); string str = sb.ToString(); Console.WriteLine(str); string s = string.Intern("Hello"); switch(str) { case "Xello": Console.WriteLine("string is Xello"); break; case "Hello": Console.WriteLine("string is Hello"); break; default: Console.WriteLine("Not Found"); break; } Console.WriteLine("Hello"); Console.ReadLine(); } 结果是: Hello Xello Not Found Xello 回复 引用 查看
对了,主要是这个连接: http://blog.joycode.com/qqchen/archive/2004/08/23/31344.aspx 对于string为什么要“特殊”处理,qqchen是这么解释的: http://blog.joycode.com/qqchen/archive/2004/08/21/31216.aspx 感谢各位牛人!!! 回复 引用 查看
在java里也有同样的情况,所以在java里要对字符串进行大量操作的话一般都用StringBuffer来操作这样可以避免多次分配内存占用系统资源.不知道C#里应该怎么做呢? 回复 引用
C#里面是StringBuilder。 回复 引用 查看
漏了一句, Console.WriteLine(str); string s = string.Intern("Hello"); 加上这句: Console.WriteLine(s); 回复 引用 查看
其实楼主从内存、算法上考虑这个问题,实际上是考虑偏了。 如果你学过设计模式,就知道实际上String类的设计是一个标准、经典的不变模式,Java、C#都是这样设计的,为什么要这样设计,楼主去google上以"不变模式“或"Immtable"搜搜就明白了。 回复 引用
按照楼上的知道找到了一篇文章。 http://www.blogbus.com/blogbus/blog/diary.php?diaryid=114805 写的挺明白了,所以转过来。 回复 引用
我想,看看Delphi是怎么实现String的对大家有好处。Delphi中的字符串有很多中,从中我们也可以看出字符串的发展历史以及演化进程。 实际上,操作系统内部使用的是copy-on-write技术。推荐一个站点,看看Delphi中的AnsiString以及WideString的实现技术会有帮助! 《A Brief History of Strings》 http://www.codexterity.com/delphistrings.htm 回复 引用 查看
to beloved,我感觉最不明白的是,string为什么要这么处理,而他处理的机制我已经比较清楚了。 这些文章,我感觉,qqchen在sumtec老大上面的第一个连接中,已经讲得很清楚了。 回复 引用 查看
谢谢:吕震宇。 我去这个连接学习学习。如有心得,继续和大家分享。 回复 引用 查看
我的观点呢:string从使用的角度应该是value type的语义(就像Integer、DateTime一样——immutable!),而从存储与执行的效率来考虑更适合实现为reference type——因此这个差异就自然的应该由CLR来透明化了——而实现这个的技术就是copy-on-write。 回复 引用
http://blog.joycode.com/qqchen/archive/2004/08/23/31344.aspx#32030 其实我也只是从现象分析出来的,等我找找更精确的证据去…… :) 回复 引用
这个通常叫Copy on write 技术,就是如果一个对象的值不改变,那么对象赋值的时候,就是新声明的对象指向其欲赋值对象的指针,如果数值改变了,就新分配一个内存空间,释放掉旧的空间,这就避免了,不管对象的值是否改变都要进行值复制的开销,这个对值传递的一种策略,有时也采用引用传递就不用考虑这个了,两个对象指向同一内存空间,改变一个变量,另一个也改变。 回复 引用
编译器会把代码里每出现一个常量的string时"....."放在元数据中,运行时,每出现一个string都会去看string表中是否已存在这个string,如果已有,则把string变量指向它,如果没有,则再new一个。所以s1,s2刚开始指向同一个地址,后来指向不同的地方。而类不一样,t2=t1,指t2和t1是指向同一个地址。string不是简单的值类型,但是也不是引用类型。对stirng的处理是特殊的。 回复 引用 查看
我编写了一个程序,需要长时间不间断运行,程序里面使用了大量的string+string的语句,发现系统占用的内存一致在增长,从开始的50MB最好到200MB,然后就死了,不知道,.net的内存回收是怎么搞的 回复 引用
delphi中string似乎都是直接嵌入汇编的吧。谁安装了可以贴出来看看 回复 引用 查看
delphi的string,有一个E文的文章仔细分析过,不过忘记了。 晕,3年前的帖子,居然也被翻出来了。 回复 引用 查看
string是值类型 Test是类 是引用类型 回复 引用
Powered by: 博客园 Copyright © 鞠强