String 不可变字符串的优缺点

String 不可变字符串的优缺点,string,language-agnostic,language-design,String,Language Agnostic,Language Design,一些语言(C#或Java)具有不可变字符串,而其他语言(如Ruby)具有可变字符串。这些设计选择背后的原因是什么?至少在Java的情况下,使字符串不可变的部分原因是为了安全和线程安全。Java非常重视运行时的安全性(它最初的设计目的是允许机顶盒和web浏览器在不损害主机系统的情况下下载和执行远程内容)。为了帮助提高安全性,字符串是不可变的,不能子类化。这意味着Java运行时可以传递并接收来自用户的字符串,同时保证字符串的值保持不变(也就是说,攻击者不能对字符串进行子类化,将看似有效的字符串传递到

一些语言(C#或Java)具有不可变字符串,而其他语言(如Ruby)具有可变字符串。这些设计选择背后的原因是什么?

至少在Java的情况下,使字符串不可变的部分原因是为了安全和线程安全。Java非常重视运行时的安全性(它最初的设计目的是允许机顶盒和web浏览器在不损害主机系统的情况下下载和执行远程内容)。为了帮助提高安全性,字符串是不可变的,不能子类化。这意味着Java运行时可以传递并接收来自用户的字符串,同时保证字符串的值保持不变(也就是说,攻击者不能对字符串进行子类化,将看似有效的字符串传递到函数中,但随后更改值以获得对错误数据的访问,或者使用多个线程以使字符串在某一点上看起来正确,但随后会发生变异)


此外,不变性在多线程系统中具有效率优势,因为不必对字符串进行锁定。它还可以轻松实现子字符串操作,因为许多字符串可以共享相同的底层字符数组,尽管起点和终点不同。

如果你想一想基本数据类型是不可变的。不将整数10更改为11,而是将10替换为11。将字符串设置为基本的、不可变的,可以进行池和其他不可能的优化。

至于缺点,不可变字符串需要互补的可变数据结构(即字符串缓冲区)允许经济的追加、重新订购和其他类似操作

在不可变结构上执行此类操作将需要不合理的资源量

他对这件事很有兴趣


为了进一步反映,一些语言(如Common Lisp)同时具有非破坏性和破坏性功能,另一些语言——不可变和可变列表(Python)

引述:

如果这项任务充满了危险,为什么不把它从报告中删掉呢 语言?有两个原因:表达能力和效率。 赋值是改变共享数据的最清晰的方法 比绑定更高效。绑定会创建新的存储位置, 它分配存储,消耗额外的内存(如果 绑定从不超出范围)或对垃圾收集器征税(如果 绑定最终会超出范围)


然而,作为反例,许多JavaScript(具有不可变字符串)解释器在实现级别将字符串视为可变数组


同样,在不可变的数据结构上看起来像优雅的纯函数,但内部使用可变状态来提高效率。

不可变字符串之所以好的一个原因是它使Unicode支持变得更容易。现代Unicode不再能有效地适应固定大小的数据单元,这会破坏数据单元之间的一对一对应关系n字符串索引和内存地址,使可变字符串具有优势


在过去,大多数西方应用程序使用单字节字符(各种基于ASCII的编码,或EBCDIC…),因此通常可以通过将字符串作为字节缓冲区(如传统的C应用程序)来有效地处理它们

当Unicode相当新的时候,对前16位以外的内容没有太多要求,因此Java使用双字节字符作为
String
s(和
StringBuffer
s)。这使用了两倍的内存,并忽略了超过16位的Unicode扩展可能出现的任何问题,但当时它很方便

现在Unicode已经不是什么新鲜事了,虽然最常用的字符仍然适合16位,但你不能假装基本的多语言平面已经存在。如果你想诚实地宣称支持Unicode,你需要可变长度字符或者更大的(32位?)字符单元

对于可变长度字符,您不能再在O(1)时间内索引到任意长度的字符串——除非有额外的信息,否则您需要从头开始计数,以确定第N个字符是什么。这也扼杀了可变字符串缓冲区的主要优势:无缝修改子字符串的能力

幸运的是,大多数字符串操作实际上并不需要这种就地修改功能。词法分析、解析和搜索都是在顺序、迭代的基础上从头到尾进行的。一般的搜索和替换从一开始就不存在,因为替换字符串不必与原始字符串的长度相同


连接大量的子字符串实际上也不需要进行适当的修改来提高效率。不过,您需要更加小心,因为(正如其他人所指出的)通过为N个部分子字符串中的每一个分配一个新字符串,一个简单的连接循环可以很容易地转换为O(N^2)

避免简单连接的一种方法是提供一个可变的
StringBuffer
ConcatBuffer
对象,用于高效连接。另一种方法是包含一个不可变的字符串构造函数,该构造函数将迭代器带入要(高效)连接的字符串序列中

但是,更一般地说,可以编写一个通过引用有效连接的不可变字符串库。这种字符串通常称为“”或“cord”这表明它至少比它所组成的基本字符串要重一点,但是为了连接的目的,它要高效得多,因为它根本不需要重新复制数据


上面的维基百科链接说“rope”数据结构是O(logn)连接,但冈崎的开创性论文“展示了如何在O(1)时间内连接。

这里有一些类似的东西:@Science\u Fiction是最重要的答案