通过引用Swift传递结构?

我看过类似的问题,但是我还没有看到我满意的答案。

通过引用来传递结构是可能的还是可取的? 如果这样怎么样?

这里是一个代码作为例子的参考:

struct MyData { var contentId: Int = 0 var authorId: Int = 0 var image: UIImage = UIImage(named: "myimage") } 

正如你看到我这样做的主要原因是因为没有让我的形象倍增。

可以使用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 

除非您能certificate这是在危急情况下获得所需performance的唯一方法,否则这种做法是不鼓励的。

请注意,这样做不会节省复制UIImage的负担。 当你把一个引用types作为一个结构体的成员,你仍然只是复制引用时,你传递的价值。 您不复制图像的内容。

关于结构性能的另一个重要的事情是写入时拷贝(copy-on-write) 。 像Array这样的许多内置types都是值types,但它们非常高效。 当你在Swift中传递一个结构时,你不会承担复制它的负担,直到你改变它为止。

查看关于值types的WWDCvideo以了解更多信息。

首先,如果你传递一个结构体,它通常是按值传递的。 即使结构的所有属性都被复制,只有指向像UIImage这样的引用types的属性的指针才会被复制(只有8个字节):

 var data1 = MyData() var data2 = data1 // both data1 and data2 point to the same image 

此外,编译器优化代码,使结构通过引用在内部传递,并在需要时进行复制。

作为在顶层代码中通过引用传递结构的一个例子,你可以使用inout参数:所以一个inout参数可以通过引用传递,但Swift实现inout的一般方式是参数获取值传递,并且在函数返回后获取重新分配。

虽然编译器优化了函数调用,所以在某些情况下可以得到真正的参考。 这个优化只影响不计算的variables,或者像willSetdidSet (也可能是其他情况)那样的属性观察器。

所以你只应该依赖不在函数范围内的当前实例:

 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 

正如你所看到的, myTestt在case 1中是等价的(“true”引用语义)。 所以如果你也在函数本身中引用myTest话,这会产生巨大的差异。 但只要你不这样做,你就可以走了。