小编典典

为什么字符串在许多编程语言中都是不可变的?

java

为此选择了几种语言,例如C#,Java和Python。如果要节省内存或为进行诸如 compare之类的 操作提高效率,这对串联和其他修改操作有什么影响?


阅读 407

收藏
2020-09-08

共1个答案

小编典典

不变类型通常是一件好事:

  • 它们在并发方面更好地工作(您不需要锁定无法更改的内容!)
  • 它们减少错误:易变的对象很容易在不希望更改的情况下被更改,因为它可能会引入各种奇怪的错误(“远距离操作”)
  • 可以安全地共享它们(即对同一对象的多个引用),这可以减少内存消耗并提高缓存利用率。
  • 如果必须对可变对象进行防御性复制,则共享还会使复制非常便宜的O(1)操作成为O(n)。这很重要,因为复制是一项非常普通的操作(例如,每当您要传递参数时……)。

因此,使字符串不可变是一种非常合理的语言设计选择。

某些语言(尤其是功能语言,例如Haskell和Clojure)走得更远,几乎使所有内容变得不可变。如果您对不变性的好处感兴趣,那么这部启发性视频非常值得一看。

不可变类型有一些小的缺点:

  • 创建诸如连接之类的已更改字符串的操作会更加昂贵,因为您需要构造新对象。通常,连接两个不可变字符串的成本为O(n + m),但是如果使用像Rope这样基于树的字符串数据结构,成本可能会低至O(log(m + n))。另外,如果您确实需要有效地连接字符串,则始终可以使用Java的StringBuilder之类的特殊工具。
  • 在大字符串上进行小的更改可能会导致需要构造大字符串的全新副本,这显然会增加内存消耗。但是请注意,在垃圾回收语言中这通常不是大问题,因为如果您不保留对旧副本的引用,旧副本将很快收集垃圾。

总体而言,不变性的优点远远大于次要的缺点。即使您只对性能感兴趣,但复制的并发优势和廉价通常会使不可变字符串比具有锁定和防御性复制的可变字符串更具性能。

2020-09-08