Swift通过引用传递结构?

时间:2015-07-18 20:47:38

标签: ios swift struct

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

是否可以或建议通过引用传递结构?如果是这样的话?

以下是一个代码作为示例的参考:

Group

正如您所看到的,我这样做的主要原因是因为没有让我的图像遍布整个地方。

3 个答案:

答案 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的一般方法是参数按值传递,在函数返回后,它会被重新分配。

尽管编译器优化了函数调用,因此在某些情况下可以获得真正的引用。此优化仅影响未计算的变量或具有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仅在情况1(“真正的”引用语义)中是等效的。因此,如果您还在函数本身中引用myTest,那么这会产生巨大的差异。但只要你不这样做,你就可以去。

答案 2 :(得分:0)

结构从不通过引用传递。时期。使用结构调用 inout 会传入一个可变副本,并且该副本会在返回时覆盖调用站点。您可以在这篇文章中找到详细信息:https://chris.eidhof.nl/post/structs-and-mutation-in-swift/