2016-10-04 50 views
5

In the Swift Language Reference, under String Mutability它说:当使用var时,Swift是否有二次字符串连接?

您指示特定字符​​串是否可以修改(或突变)通过将其分配给一个变量(在这种情况下,它可以被修改),或者以恒定的(在这种情况下,它不能修改)

这我不清楚,如果“它”是可变的是变量

例如,如果我写:

var s = "" 
for i in 0...100 { 
    s += "a" 
} 

它是类似于创建NSMutableString并调用appendString 100倍(即线性成本)?

或者它是否类似于创建一系列更大的NSString实例并将它们与stringByAppendingString(即二次成本)相结合?

或者它可能会在幕后创建某种绳索结构,因此它是不可变的线性聚合?

+1

@MarkDickinson我实际上已经尝试过了,它的运行速度超出了我的预期。所以这似乎意味着可变的。但是,当两个可变变量彼此相等时,更新一个不会更新另一个变量,这意味着不可变。从语言设计的角度来看,将运行时类型信息放入var-vs-val似乎很奇怪。所以我真的不确定它是什么。 –

回答

2

追加到像这样的集合(而String本身不是一个集合,你基本上追加到它的characters视图与该代码)是线性的,而不是二次的。 Swift中的一个字符串有一个内部缓冲区,每当它填满时它的大小就会增加一倍,这意味着当你重复追加时,你会看到越来越少的重新分配。该文档描述了以这种方式作为“分期付款”O(1)操作追加:大部分时间追加为O(1),但偶尔需要重新分配字符串的存储空间。

数组,集合和字典具有相同的行为,但如果您知道您将多次添加数组,则您也可以为数组保留特定容量(使用reserveCapacity(_:))。


所有这些集合都使用“copy-on-write”来保证值语义。在这里,xy共享缓存:

let x = "a" 
let y = x 

如果发生变异x,它得到缓冲的一个新的,独特的副本:

x += "b" 
// x == "ab" 
// y == "a" 

之后,x都有自己的缓冲区,因此后续突变不需要复制。

x += "c" // no copy unless buffer is full 
+0

这是乞求链接到stdlib源;-) – jtbandes

+0

@jtbandes如何链接到文档? ;)https://developer.apple.com/reference/swift/string#2621389 –

+0

你可以进入更多关于'var string'语义的细节来证明这个答案吗?例如,为什么'var x =“a”; var y = x; x + =“b”; print(y)'如果只添加一个公共缓冲区,就打印“a”而不是“ab”? –