我看过类似的问题,但我还没有看到我满意的答案。
是否可以或建议通过引用传递结构?如果是这样的话?
以下是一个代码作为示例的参考:
Group
正如您所看到的,我这样做的主要原因是因为没有让我的图像遍布整个地方。
答案 0 :(得分:36)
可以使用inout
关键字和&
运算符通过引用传递结构。
struct Test {
var val1:Int
let val2:String
init(v1: Int, v2: String) {
val1 = v1
val2 = v2
}
}
var myTest = Test(v1: 42, v2: "fred")
func change(test: inout Test) {
// you can mutate "var" members of the struct
test.val1 = 24
// or replace the struct entirely
test = Test(v1: 10, v2: "joe")
}
change(test: &myTest)
myTest // shows val1=10, val2=joe in the playground
除非您能证明这是在紧急情况下获得所需性能的唯一途径,否则不鼓励这种做法。
请注意,这样做不会节省复制UIImage的负担。将引用类型作为结构的成员放置时,仍然只能在按值传递时复制引用。您没有复制图像的内容。
了解结构性能的另一个重要事项是写时复制。像Array这样的许多内置类型都是值类型,但它们非常高效。当你在Swift中传递一个结构时,你不会承担复制它的负担,直到你改变它为止。
查看WWDC video on value types了解详情。
答案 1 :(得分:4)
首先,如果你传递一个结构,它通常按值传递。即使结构的所有属性都被复制,只有指向UIImage等引用类型的属性的指针才会重复(只有8个字节):
var data1 = MyData()
var data2 = data1
// both data1 and data2 point to the same image
此外,编译器会优化代码,以便结构通过引用在内部传递,并在需要时复制。
作为在顶级代码中通过引用传递结构的示例,您可以使用inout
个参数:
因此inout
参数可以通过引用传递,但Swift实现inout
的一般方法是参数按值传递,在函数返回后,它会被重新分配。
尽管编译器优化了函数调用,因此在某些情况下可以获得真正的引用。此优化仅影响未计算的变量或具有willSet
和didSet
等属性观察者的变量(可能还有其他情况)。
所以你应该只依赖不在函数范围内的当前实例:
struct Test {
var value = 0
}
// case 1
var myTest = Test()
// case 2
var myTest = Test() {
didSet { print("I was set") }
}
// case 3
var myTest: Test {
get{ return Test() }
set{ print("I set myself") }
}
func mutateTest(inout t: Test) {
// directly referencing to myTest
myTest.value // value = 0 in all cases
t.value = 42
myTest.value // value = 42 in case 1 ; value = 0 in case 2 and 3
t = Test() // nothing gets printed
myTest.value // value = 0 in all cases
t = Test() // nothing gets printed
t.value = 3 // value = 3 in case 1 ; value = 0 in case 2 and 3
}
changeTest(&myTest)
//case 2: "I was set", case 3 "I set myself" get printed now
myTest.value // value = 3 in all cases
正如您所看到的,myTest
和t
仅在情况1(“真正的”引用语义)中是等效的。因此,如果您还在函数本身中引用myTest
,那么这会产生巨大的差异。但只要你不这样做,你就可以去。
答案 2 :(得分:0)
结构从不通过引用传递。时期。使用结构调用 inout 会传入一个可变副本,并且该副本会在返回时覆盖调用站点。您可以在这篇文章中找到详细信息:https://chris.eidhof.nl/post/structs-and-mutation-in-swift/