我们鼓励在Swift中使用struct
而不是class
。
这是因为
malloc
/ free
调用 struct
变量的缺点是每次从函数返回或分配给函数时都会复制它们。显然,这也可能成为瓶颈。
E.g。想象一个4x4矩阵。 16每个分配/返回都必须复制16个浮点值,这些值在64位系统上为1� 024位。
可以避免这种情况的一种方法是在将变量传递给函数时使用inout
,这基本上是Swifts创建指针的方法。但是,我们也不鼓励使用inout
。
所以对我的问题:
我应该如何处理Swift中的大型不可变数据结构?
我是否需要担心创建一个有很多成员的大struct
?
如果是的话,我什么时候越线?
答案 0 :(得分:3)
来自Swift Reference的this页面的最底部:
请注意
上面的描述是指字符串,数组和字典的“复制”。您在代码中看到的行为将始终如同副本一样。但是,当绝对必要时,Swift仅在幕后执行实际复制。 Swift管理所有值复制以确保最佳性能,您不应该避免分配以尝试抢占此优化。
我希望这能回答你的问题,如果你想确保数组不被复制,你总是可以将参数声明为inout
,并将&array
传递给功能
同样,类会增加很多开销,只有在你真的必须引用同一个对象时才应该使用它。
结构的例子:
课程示例:
答案 1 :(得分:2)
这个接受的答案并不能完全回答你的问题:Swift总是复制结构。 Array / Dictionary / String / etc的作用是它们只是类的包装(包含实际存储的属性)。这样,sizeof(Array)就是指向该类(MemoryLayout<Array<String>>.stride == MemoryLayout<UnsafeRawPointer>.stride
)
如果你有一个非常大的结构,你可能想要考虑将它的存储属性包装在一个类中,以便有效地作为参数传递,并在变异之前检查isUniquelyReferenced
以给出COW语义。
结构具有其他效率优势:它们不需要引用计数,并且可以由优化器进行分解。
在Swift中,值保留其数据的唯一副本。有几个 使用值类型的优点,例如确保值具有 独立国家。当我们复制值(赋值的效果, 初始化和参数传递)程序将创建一个新的 价值的副本。对于一些大的值,这些副本可能是时间 消耗和伤害程序的性能。
https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#the-cost-of-large-swift-values
关于容器类型的部分:
请记住,在使用大值类型之间需要权衡 并使用引用类型。在某些情况下,复制的开销 并且移动大值类型将超过删除的成本 桥接和保留/释放开销。