当按降序对数字进行排序时,我有这个函数来快速 Select 分区.该函数引用了在其作用域之外定义的arr(分区是另一个函数中的嵌套函数).

我的问题是,由于SWIFT中的数组是值类型,所以当我进行交换时,每次都会创建一个新的副本吗?或者相同的内存被覆盖了吗?

将函数定义为partition(start: Int, end: Int, arr: inout [(Int, Int)])是不是更好,这样arr就可以通过引用传递?

接下来的问题,当我们做arr.append((4, 8))时会发生什么?这会在内存中创建一个新的副本吗?

var arr = [(Int, Int)]() // [(1, 2), (3, 5), (2, 8)]
func partition(start: Int, end: Int) -> Int {
    var swap = start 

    for i in start..<end {
        if arr[i].1 > arr[end].1 {
            (arr[i], arr[swap]) = (arr[swap], arr[i]) // arr copied on write?
            swap += 1
        }
    }
    (arr[end], arr[swap]) = (arr[swap], arr[end]) // arr copied on write?
    return swap
}

推荐答案

你交换every次也不会产生副本.

在这种情况下,您似乎误解了写入时复制的含义.我们说SWIFT数组是写入时拷贝,并不是因为我们every次写入它,就会创建拷贝.

写入时复制的意思是"在100上复制",而不是"只要 struct 被复制就复制".您可能会将其误解为"写入时使用101",而不是"写入时继续使用相同的存储".如果它是这样工作的,它就不会被称为"优化":)

考虑var foo = bar,其中foobar是array.bar的内容不会复制到foo,因为没有writes.foobar共享相同的内部缓冲区,直到barfoo被写入,此时将创建副本.

另请参阅Arraydocumentation:

数组与标准库中所有大小可变的集合一样, 使用写入时复制优化.数组的多个副本共享 相同的存储空间,直到您修改其中一个副本.当这种情况发生时, 要修改的数组将其存储替换为唯一拥有的 自身的副本,然后在适当的位置进行修改.优化是 有时应用它可以减少复制量.

这意味着,如果一个数组与其他拷贝共享存储, 在该数组上的第一个变异操作会产生复制 array.作为其存储的唯一所有者的数组可以执行 变异操作就位.

如果像您的代码中一样,只有一个数组变量,则不需要复制.所有写入都可以写入同一数组的内部缓冲区.该数组的工作原理与任何其他 struct 一样--其原理与将 struct 的属性赋值1000次不会复制该 struct 的原理相同.

var s = SomeStruct()
for _ in 0..<1000 {
    s.property = ... // this won't copy s 1000 times
}

如果在调用partition之前先将arr赋给另一个变量,则在第一次交换时将创建一个副本,此后不会再创建副本.

至于调用append,数组可能需要增加其capacity以追加新元素.如果为count == capacity,则需要分配新内存.这might步涉及重新定位数组的内容,您可以将其视为"复制":

当数组在追加之前需要重新分配存储或其存储与另一个拷贝共享时,追加为O(N),其中n是数组的长度.

Swift相关问答推荐

为表单部分赋予背景 colored颜色 /渐变

在Swift中initt()完成后运行一个函数

RealityKit如何获得两个相对大小相同的ModelEntity?

如何使用变量 Select 哪个向量(?)在我的 struct 中密谋吗?

正在接收具有不完整数据错误的URL请求

如何打印出此 struct 中的数据?

如何在 Combine 合并运算符的输出上使用 eraseToAnyPublisher

在 Swift 中增量写入大型文本文件的最佳方法

格式化大货币数字

如何在 SWIFTUI 中旋转修剪?

如何更新 UserDefault 中的特定值

'NSLog' 不可用:可变参数函数在 swift 中不可用

如何在 SwiftUI 中打开 ImagePicker?

iOS:检测设备是否为 iPhone X 系列(无框)

如何更改弹出框的大小

Swift - 迭代 struct 对象时如何对其进行变异

在 Swiftui 中是否有一种简单的方法可以通过捏合来放大图像?

在 xcode8 中找不到 ModuleName-Swift.h 文件

如何在 Swift 中从字符串创建类的实例

NSLocationWhenInUseUsageDescription 警告,但我已经添加了