Swift 使用 var 时是否有二次字符串连接?
Does Swift have quadratic string concatenation when using var?
In the Swift Language Reference, under String Mutability 它说:
You indicate whether a particular String can be modified (or mutated) by assigning it to a variable (in which case it can be modified), or to a constant (in which case it cannot be modified)
我不清楚可变的"it"是变量还是值。
例如,如果我写:
var s = ""
for i in 0...100 {
s += "a"
}
是否类似于创建一个 NSMutableString
并调用 appendString
100 次(即线性成本)?
或者它类似于创建一系列更大的 NSString
实例并将它们与 stringByAppendingString
组合(即二次成本)?
或者它可能在幕后创建了某种绳索结构,所以它是不可变的并且 总体上是线性的?
像这样附加到一个集合(虽然 String
本身不是一个集合,但您实际上是用该代码附加到它的 characters
视图)是线性的,而不是二次的。 Swift 中的字符串有一个内部缓冲区,每当它填满时,其大小就会加倍,这意味着当你重复追加时,你会看到越来越少的重新分配。文档将以这种方式追加描述为 "amortized" O(1) 操作:大部分时间追加是 O(1),但偶尔需要重新分配字符串的存储。
数组、集合和字典具有相同的行为,但如果您知道要追加多次,也可以为数组保留特定容量(使用 reserveCapacity(_:)
)。
所有这些集合都使用 "copy-on-write" 来保证值语义。这里,x
和y
共享一个缓冲区:
let x = "a"
let y = x
如果你改变 x
,它会得到一个新的、唯一的缓冲区副本:
x += "b"
// x == "ab"
// y == "a"
在那之后,x
有自己的缓冲区,因此后续的突变将不需要副本。
x += "c" // no copy unless buffer is full
In the Swift Language Reference, under String Mutability 它说:
You indicate whether a particular String can be modified (or mutated) by assigning it to a variable (in which case it can be modified), or to a constant (in which case it cannot be modified)
我不清楚可变的"it"是变量还是值。
例如,如果我写:
var s = ""
for i in 0...100 {
s += "a"
}
是否类似于创建一个 NSMutableString
并调用 appendString
100 次(即线性成本)?
或者它类似于创建一系列更大的 NSString
实例并将它们与 stringByAppendingString
组合(即二次成本)?
或者它可能在幕后创建了某种绳索结构,所以它是不可变的并且 总体上是线性的?
像这样附加到一个集合(虽然 String
本身不是一个集合,但您实际上是用该代码附加到它的 characters
视图)是线性的,而不是二次的。 Swift 中的字符串有一个内部缓冲区,每当它填满时,其大小就会加倍,这意味着当你重复追加时,你会看到越来越少的重新分配。文档将以这种方式追加描述为 "amortized" O(1) 操作:大部分时间追加是 O(1),但偶尔需要重新分配字符串的存储。
数组、集合和字典具有相同的行为,但如果您知道要追加多次,也可以为数组保留特定容量(使用 reserveCapacity(_:)
)。
所有这些集合都使用 "copy-on-write" 来保证值语义。这里,x
和y
共享一个缓冲区:
let x = "a"
let y = x
如果你改变 x
,它会得到一个新的、唯一的缓冲区副本:
x += "b"
// x == "ab"
// y == "a"
在那之后,x
有自己的缓冲区,因此后续的突变将不需要副本。
x += "c" // no copy unless buffer is full