swift2 - 使用 inout 关键字 : is the parameter passed-by-reference or by copy-in copy-out (/call by value result)

标签 swift2 inout

问题:基于以下信息和讨论:inout 参数是通过引用传递还是通过复制传入复制输出

<小时/>

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

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

<小时/>

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

In-out parameters are passed as follows:

When the function is called, the value of the argument is copied. In the body of the function, the copy is modified. When the function returns, the copy’s value is assigned to the original argument. This behavior is known as copy-in copy-out or call by value result. ...

... You write an in-out parameter by placing the inout keyword at the start of its parameter definition. An in-out parameter has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value. ...

<小时/>

现在以我自己的例子为例,试图调查这一点:

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. 我是否误解了Apple语言文档中inout的描述,它可以解释为“按引用传递”吗?
  2. 或者,我的例子还不能代表这个案例吗?

最佳答案

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

In-Out Parameters

This behavior is known as copy-in copy-out or call by value result. For example, when a computed property or a property with observers is passed as an in-out parameter, its getter is called as part of the function call and its setter is called as part of the function return.

As an optimization, when the argument is a value stored at a physical address in memory, the same memory location is used both inside and outside the function body. The optimized behavior is known as call by reference; it satisfies all of the requirements of the copy-in copy-out model while removing the overhead of copying. Do not depend on the behavioral differences between copy-in copy-out and call by reference.

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

关于swift2 - 使用 inout 关键字 : is the parameter passed-by-reference or by copy-in copy-out (/call by value result),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34400600/

相关文章:

swift - 测量 NSURLSession 的 dataTaskWithRequest 的总响应时间

ios - 函数应返回字符串或数组

ios - 如何从 Eureka 中的 ImageRow 访问所选图像?

swift - 协议(protocol)扩展初始化器

Swift inout 如何在未更改时不复制回属性,以不触发对象 setter

ios - 无法将 'NSLayoutConstraint' 类型的不可变值作为 inout 参数传递

ios - NSURLSession 返回元组的问题

swift - Swift 中 “+=” 运算符的内存安全

const 属性的 Swift inout 参数

arrays - 更新通过引用传递的数组中的项目