问题:根据以下信息和讨论:inout
参数是通过引用传递的还是通过复制输入复制输出传递的?
基于以下SO线程,inout
关键字标记的函数参数是通过引用传递的:
- inout/var参数与引用类型有什么不同吗
- Swift传递值还是传递引用
- 为什么不';是否通过引用传递
我们注意到,最顶端的两个线程是Swift 2.0之前的线程;我在SO上找不到任何关于这个主题的新讨论(除了有点相关的第三线程链接)。
然而,根据苹果的文档(据我所知),由inout
关键字标记的函数参数由复制输入复制输出(或按值调用结果)传递
- Apple语言参考:声明-输入输出参数:
输入输出参数传递如下:
调用函数时,将复制参数的值。在里面函数的主体,副本被修改。当函数返回时,副本的值被分配给原始参数。这行为被称为复制入复制出或按值调用结果。。。
- Apple语言指南:函数-输入输出参数:
通过将inout关键字放在开始其参数定义。输入输出参数有一个值即传递到函数的被函数修改,并且被传递回函数以替换原来的值。。。
现在以我自己的例子来研究这个:
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
参数是否通过引用传递?
我有两个可能的后续问题:
- 我是否误解了苹果语言文档中对
inout
的描述,是否可以解释为"通过引用" - 或者,我的例子是否仍然不能代表本案
语言参考中接下来的两段更详细地描述了它:
输入输出参数
…
这种行为被称为复制入复制出或按值调用结果。对于例如,当计算的属性或具有观察者的属性作为in-out参数传递,它的getter作为函数调用及其setter作为函数返回的一部分进行调用。
作为优化,当参数是存储在地址,内部和在功能体之外优化后的行为称为调用引用;它满足中副本的所有要求复制模型,同时消除复制的开销不要依赖复制输入复制输出与调用输出行为的差异参考
因此,它实际上是"通过引用"