> On May 6, 2017, at 9:33 PM, Kelvin Ma via swift-users <swift-users@swift.org> > wrote: > > If I have a “large” struct like > > struct Vertex > { > let x:Double, y:Double > var r:Int, g:Int, b:Int > let s:Double, t:Double > var selected:Bool > } > > and I want to pass it to a function without modifying it like > > func taxicab_distance(_ v1:Vertex, _ v2:Vertex) -> Double > { > return v2.x - v1.x + v2.y - v1.y > } > > Will the entire struct Vertex get copied and pushed onto the stack, or will > only the relevant members be passed to the function? > > In other words, does the compiler know to optimize this call down to > > func taxicab_distance(v2x:Double, v1x:Double, v2y:Double, v1y:Double) -> > Double > { > return v2x - v1x + v2y - v1y > }
When passed as an argument, a struct is recursively broken up into individual primitives, and each of those is passed in separate arguments. (The primitive types in question are mostly special "builtin" types which are wrapped by standard library types like `Int` and `Double`.) As far as I'm aware, there is no optimization that removes unused parts of the struct. That means this would be passed as something like: func taxicab_distance(_ v1.x._value: Builtin.Float64, _ v1.y._value: Builtin.Float64, _ v1.r._value: Builtin.Int64, _ v1.g._value: Builtin.Int64, _ v1.b._value: Builtin.Int64, _ v1.s._value: Builtin.Float64, _ v1.t._value: Builtin.Float64, _ v1.selected._value: Builtin.Int1, _ v2.x._value: Builtin.Float64, _ v2.y._value: Builtin.Float64, _ v2.r._value: Builtin.Int64, _ v2.g._value: Builtin.Int64, _ v2.b._value: Builtin.Int64, _ v2.s._value: Builtin.Float64, _ v2.t._value: Builtin.Float64, _ v2.selected._value: Builtin.Int1) -> Builtin.Float64 { … } Because of this, it may sometimes make sense to convert large structs into copy-on-write types by hand—basically, make a struct which wraps an inner class type, guarding all mutations with an `isUniquelyReferenced(_:)` check. (You're right that there's no implicit copy-on-write behavior in structs currently—when a struct has copy-on-write behavior, it has been manually implemented that way.) Note that this may not always be the case: There's a built-in copy-on-write optimization which will soon come to instances which have been cast to a protocol type, and the "resilient" structs planned for a future version of Swift will probably be passed by reference in some way. But I believe that's the state of things in Swift 3. -- Brent Royal-Gordon Architechies
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users