是否有swiftc编译器优化来删除不必要的大变量?

时间:2017-12-12 15:13:50

标签: swift compiler-optimization

当我编写具有高阶函数的代码时,我发现一次写出一个转换表达式会更加清晰:

let children = objects.map { $0.children }
let validChildren = children.filter { $0.isValid }
let sortedChildren = validChildren.sorted { $0.count < $1.count }

但是,我知道这些函数中的每一个都返回一个新的Array对象,我将它存储到一个变量中,所以理论上我每次创建并持有一个新的Array并浪费大量内存。最好将调用写为一行,以便在使用后销毁不必要的数组。

let sortedChildren = objects.map { $0.children } .filter { $0.isValid } .sorted { $0.count < $1.count }

但是稍后阅读会更加烦人,因为在一行代码中会发生很多事情。所以我的问题是:Swift的编译器是否有优化来原谅我的挑剔并在编译时删除未使用的变量?

2 个答案:

答案 0 :(得分:1)

@MartinR在问题评论中提到了这一点,但值得一个正式答案和来源。

As per the Swift repository docs:

  

Swift中的所有标准库容器都是使用COW的值类型   (copy-on-write)[4]执行复制而不是显式复制。在   在许多情况下,这允许编译器通过它来消除不必要的副本   保留容器而不是执行深层复制。这是   仅通过复制基础容器(如果引用计数)来完成   容器大于1,容器发生变异。对于   在下面的实例中,分配d时不会发生复制   c,但当d通过附加2进行结构变异时,d将是   复制,然后2将附加到d:

var c: [Int] = [ ... ]
var d = c        // No copy will occur here.
d.append(2)      // A copy *does* occur here.

由于高阶函数不会修改它们被调用的对象,因此可以高度放心地说结果针对大小进行了优化。

答案 1 :(得分:1)

两个版本之间没有区别。

即使您没有将结果分配给变量,也会创建一个新的列表实例,以便存储函数调用的结果。因此,内存使用情况是相同的。

objects.map { $0.children }.filter { $0.isValid }.sorted { $0.count < $1.count }

所以在每次函数调用之后,我们仍然需要内存来存储该函数的结果,无论你是assign它还是变量。并且assigning到另一个变量不会制作该对象的任何副本。