字符串的不变性

发布时间:2019-08-06 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了字符串的不变性脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

像是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,请注明来意。