1
invite 2015-02-19 18:29:31 +08:00
不懂。
|
2
shawnclovie 2015-02-19 18:47:09 +08:00
因为把字符串设计成如int一样的基础类型,其它的基础类型都是不可变的。
而且,这样的设计可以减少很多程序设计中的意外的发生。 |
3
amyangfei 2015-02-19 18:50:01 +08:00
[What is the benefit of string being immutable in Go language](http://www.quora.com/What-is-the-benefit-of-string-being-immutable-in-Go-language)
|
5
fwrq41251 2015-02-19 18:55:26 +08:00 via Android
|
7
shawnclovie 2015-02-19 19:03:48 +08:00
C code:
const char *a = "ABC"; // 不想让它改变的值,比如是一个全局设置之类 void tolower(char *str){ for (int i = 0; i < strlen(str); ++ i){ ((char *)str)[i] += 32; } } tolower((char *)a); // a就变小写了。 |
8
xguru 2015-02-19 19:04:41 +08:00
http://stackoverflow.com/questions/9544182/why-are-strings-immutable-in-many-programming-languages
immutable types are a good thing generally: They work better for concurrency (you don't need to lock something that can't change!) They reduce errors: mutable objects are vulnerable to being changed when you don't expect it which can introduce all kinds of strange bugs ("action at a distance") They can be safely shared (i.e. multiple references to the same object) which can reduce memory consumption and improve cache utilisation. Sharing also makes copying a very cheap O(1) operation when it would be O(n) if you have to take a defensive copy of a mutable object. This is a big deal because copying is an incredibly common operation (e.g. whenever you want to pass parameters around....) |
9
EPr2hh6LADQWqRVH 2015-02-19 19:20:35 +08:00
哦?难道不是因为内存管理的原因?
|
10
incompatible 2015-02-19 19:52:23 +08:00
mutable真的算不上什么好设计。需要一个新的值,你就构造一个新的对象就好了啊。何必如此吝惜内存非要复用先前的对象?
参见java中的java.util.Date和java.util.Calendar。用了JodaTime后,真的是感觉被解放了 |
11
tairan2006 2015-02-19 21:48:01 +08:00
不可变的好管理啊…除了C/C++,大部分语言的string都是不可变的吧。
|
12
coolcfan 2015-02-19 21:50:48 +08:00
不可变对象对线程安全有非常大的好处。
|
14
chingli 2015-02-19 22:09:10 +08:00
http://www.importnew.com/7440.html
安全、性能,以及可用来实现一些特殊作用。 Go中的字符串是utf-8编码,同一个字符串,不同的字符可能分别占用1、2、3字节,方便使用range遍历。 |
15
ovear 2015-02-19 22:35:08 +08:00
=.= 刚好窝对Java的机制稍微熟悉点,详细解释下吧
1、同步\安全 2、性能\省资源 3、简单 首先,在Java里面,String是一个对象。 1、对于在对象中传引用的Java,如果String是可变的,那么将会导致Java的String机制完全毁灭。 于是Java就采取了一种简单又暴力的做法,直接把Java的String设定为不可变的,这样既解决了传引用问题,又可以解决同步/安全问题。 2、为什么说会提升性能,节省资源呢? 如果String是可变的,那么如果程序中有许多相同的String呢?那不是会产生很多相同的String,多浪费资源。 于是Java有了String Pool----下面是我研究时候做的一些笔记 ----------笔记-------- 26. String是常量,其对象一旦创建完毕就无法改变。当使用+拼接字符串时,会生成新的String对象,而不是向原有的String对象追加内容。 27. String Pool(字符串池) 28. String s = “aaa”;(采用字面值方式赋值) 1) 查找String Pool中是否存在“aaa”这个对象,如果不存在,则在String Pool中创建一个“aaa”对象,然后将String Pool中的这个“aaa”对象的地址返回来,赋给引用变量s,这样s会指向String Pool中的这个“aaa”字符串对象 2) 如果存在,则不创建任何对象,直接将String Pool中的这个“aaa”对象地址返回来,赋给s引用。 29. String s = new String(“aaa”); 1) 首先在String Pool中查找有没有“aaa”这个字符串对象,如果有,则不在String Pool中再去创建“aaa”这个对象了,直接在堆中(heap)中创建一个“aaa”字符串对象,然后将堆中的这个“aaa”对象的地址返回来,赋给s引用,导致s指向了堆中创建的这个“aaa”字符串对象。 2) 如果没有,则首先在String Pool中创建一个“aaa“对象,然后再在堆中(heap)创建一个”aaa“对象,然后将堆中的这个”aaa“对象的地址返回来,赋给s引用,导致s指向了堆中所创建的这个”aaa“对象。 -------------- 简单粗暴,有什么不好呢? |
16
ovear 2015-02-19 22:36:48 +08:00
|
17
snnn OP C++难道就没有StringPool吗? VC早在上个世纪就对常量字符串做了pool。
https://msdn.microsoft.com/en-us/library/s0s0asdt.aspx 而且C++的std::string本身就是支持引用计数的,要想做pool易如反掌。拿libstdc++来说,每当被修改的时候,检查Rep对象是不是来自静态的pool,如果是,Copy一份再修改之。鉴于大部分string都是不需要被modify的,这么做不会有性能损失。 |
19
ovear 2015-02-19 22:54:51 +08:00
@snnn 这是合法的 有问题么?
关于你说的vc提供的是 [编译时] [编译时] 优化,Java是[运行时] [运行时]优化好么?完全都不同的东西 Gets or sets a value indicating whether to enable read-only string pooling for generating smaller compiled code. 需要我翻译一遍么? generating smaller compiled code. 生成更小的文件 这个指的是在编译的时候 string a = 'abc'; string b = 'abc'; 优化后变成 string a = 'abc'; string b = a; lz真的认真看了么? 对啦,告诉lz个小技巧,把巨硬的en-us换成zh-cn可以看中文噢,有翻译的说。 比如说 https://msdn.microsoft.com/zh-cn/library/s0s0asdt.aspx |
21
denghongcai 2015-02-20 01:20:29 +08:00
@hx1997 只要上面没写明是机器翻译的,就是人工校对过的,我还真没发现和英语版本有什么区别,都是严谨的
|
22
hx1997 2015-02-20 02:01:00 +08:00
@denghongcai 当然没区别了,逐字逐句翻译的呢。
Preparing to recycle... 正在准备 重循环 The memory could not be "written". 内存不能为"written"。 Enables the compiler to create a single copy of identical strings in the program image and in memory during execution. 启用编译器在程序映像和执行时的内存中创建相同字符串的一个副本。 |
23
xiaowangge 2015-02-20 07:21:43 +08:00 via Android
ovear 你的笔记借鉴 张龙老师的了(^_^)
|
24
reus 2015-02-20 18:55:33 +08:00 via Android
go里的string就是不可写的[]byte,所以这只是一种补充。string可以作为map的key,可以按rune来range。所以如果需要可变的字符串类型,就用[]byte或者[]rune即可。
|
25
ovear 2015-02-21 19:09:39 +08:00
@xiaowangge 0 0 对。。刚好百度到那时候,看的讲得不错就拷过来啦。。后来一直想不起是谁讲的_(:з」∠)_
|
26
knightzorro 2015-02-25 10:01:43 +08:00
不仅java go, c# python lua等语言里面的字符串也是不可变的,究其原因,我贡献一个不是那么理论化的观点,string用的太多,string实质上是个数组,使用的时候都是用引用(传值性能太差),这样就造成了一块内存多个reader,如果允许可变就是多个writer, 内容正确性没法保证。
|