脚本宝典收集整理的这篇文章主要介绍了字符串的不变性,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
像是js,以及c#等一系列的语言,推出任何一个特征都要和c比一比,你知道的:)。
string的不可变性也是一样,你看:
C的string是可以改变的。
你可以
char str[] = "Foo";
str[0] = ‘G'
str的内容确实被改变了。可以通过PRint来证明。打印内容,也打印指针。指针不变,内容变了。
2.js的不可改.如下的代码,没有任何效果,也可以LOG出来证明
VAR str = "foo";
str[0] = 'g' ;
因为,语义上来说,这样做意味着原位修改str的内存区内容
但是你可以
var str = "foo";
var = 'bar'
因为原位置的内存没有修改,是新分配的。只是打印不了指针,不好直接证明。要么就看代码,那就啰嗦了。非常非常的啰嗦。
不少语言对字符串的实现,都采用了限定不变性。不能说这是不费解的:为何去创建一个新字符串,而不是去修改它呢?毕竟c就是这样做的。
字符串的不可变性有不少好处,但是如果程序员忘了这一点也会导致问题。
如下的c#代码会创建10000个字符串对象,但是除了最后一个,后面都是垃圾需要被回收的。
string s = string.Empty;
for (int i = 0; i < 10000; i++)
{
s += "x";
}
通过cld profiler可以看到这张图。
这样的场景应该使用StringBuilder。而不是字符串连接。
StringBuilder sb = StringBuilder();
for( i = ; i < 10000; i++)
{
sb.Append();
}
string x = sb.ToString();
针对js,也可以自己做一个StringBuilder
function StringBuilder@H_109_126@() {
this._array = [];
this._index = 0;
}
StringBuilder.prototype.append = function (str) {
this._array[this._index] = str;
this._index++;
}
StringBuilder.prototype.toString = function () {
return this._array.join('');
}
为何设计者决定实现不可变字符串呢?
这个和存储优化有关。字符串都存储在俘虏池(intern pool)内,因为string都在intern pool内,所以,相同的字符串引用一致。这样的存储效果很好。
可是,如果允许修改string,那么a修改了,b也会跟着修改,d也是。可是,语义上来说,我们认为他们是不同的变量,不应该联动。所以字符串不可变就是intern pool存储的代价。
string a = "xx";
string b = "xx";
string c = "x";
string d = String.Intern(c + c);
Console.WrITeLine((object)a == (object)b); Console.WriteLine((object)a == (object)d);
String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,c# 查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;
不变性,对多线程应用是有好处的。
另一个场景是字符串可以用于哈希表的键,而键是不可以改变值的。
string key = "abc";
Hashtable ht = new Hashtable();
ht.Add(key, 123);
key = "xbc";
Console.WriteLine(key); // xbc
Console.WriteLine(ht["abc"]); // 123
以上是脚本宝典为你收集整理的字符串的不变性全部内容,希望文章能够帮你解决字符串的不变性所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。