6

问题:根据下面的信息和讨论:inout参数是通过引用传递还是通过复制复制输出


基于以下 SO 线程,以inout关键字标记的函数参数通过引用传递

我们注意到最上面的两个线程是 Swift 2.0 之前的版本;我在 SO 上找不到关于这个主题的任何更新的讨论(除了有点相关的第三个线程链接)。


但是,根据 Apple 的文档(据我所知),由inout关键字标记的函数参数是通过copy-in copy-out传递的(或按值调用 result

传入传出参数如下:

当函数被调用时,参数的值被复制。在函数体中,副本被修改。当函数返回时,副本的值被分配给原始参数。这种行为称为复制输入复制输出或按值调用结果。...

...您通过将 inout 关键字放在其参数定义的开头来编写一个 in-out 参数。一个 in-out 参数有一个值,它被传入函数,被函数修改,并被传回函数以替换原始值。...


现在以我自己的示例为例,尝试对此进行调查:

struct MyStruct {
    private var myInt: Int

    mutating func increaseMyInt() {
        myInt++
    }

    func printMyInt() {
        print(String(myInt))
    }

    init(int: Int) {
        myInt = int
    }
}

class MyClass {
    var myStruct: MyStruct

    init(int: Int) {
        myStruct = MyStruct(int: 1)
    }

    func printMyStructsInt() {
        print(String(myStruct.printMyInt()))
    }
}

func myInOutFunc(inout myLocalStruct: MyStruct, myClass: MyClass) -> Int {
    myClass.printMyStructsInt() // prints "1", OK
    myLocalStruct.increaseMyInt()
    myClass.printMyStructsInt() // prints "2": so myStruct is not a copy here?
    myLocalStruct.increaseMyInt()

    return 0
        // according to Apple's doc, shouldn't myStruct member of myClass get
        // assigned (copy of) value of myLocalStruct at this point, and not
        // prior to this?
}

var a = MyClass(int: 1)

a.printMyStructsInt() // prints "1", OK
myInOutFunc(&a.myStruct, myClass: a)
a.printMyStructsInt() // prints "3", OK

这个例子意味着inout参数确实是通过引用传递的(正如上面两个链接的 SO 线程中所指出的那样)。由于我们在 inout 参数前加上一个 & 符号 ( &),这确实“感觉”合乎逻辑。

为了尽力确保我的示例具有代表性——因为这里的inout参数myLocalStruct是作为类属性发送的——我还确保myLocalStruct没有得到一些“幕后”引用,因为它是类属性:

// ... add to bottom of the code above

func testSendStructAsPublicClassProperty(var myLocalStruct: MyStruct) {
    myLocalStruct.increaseMyInt()
}

// test that sending class property doesn't "reference" things up
a.printMyStructsInt() // prints "3"
testSendStructAsPublicClassProperty(a.myStruct)
a.printMyStructsInt() // prints "3", OK (only copy of class property is sent)

好的,myLocalStruct在这个例子中真的是函数局部的,因此是按值传递的(没有在引擎盖后面的引用)。


结果:鉴于上述情况,inout参数是通过引用传递的吗?

我有两个可能的后续问题:

  1. 我是否误解了inoutApple 语言文档中的描述,可以将其解释为“通过引用传递”吗?
  2. 或者,我的例子仍然不能代表这种情况吗?
4

1 回答 1

2

语言参考中的接下来的两段更详细地描述了它:

输入输出参数

这种行为称为复制输入复制输出或按值调用结果。例如,当计算属性或具有观察者的属性作为输入输出参数传递时,它的 getter 作为函数调用的一部分被调用,它的 setter 作为函数返回的一部分被调用。

作为优化,当参数是存储在内存中物理地址的值时,函数体内部和外部都使用相同的内存位置。优化的行为称为引用调用;它满足了copy-in-copy-out模型的所有要求,同时消除了复制的开销。不要依赖于复制输入复制输出和引用调用之间的行为差​​异。

所以它实际上是“通过引用传递”

于 2015-12-21T17:00:02.193 回答