代码之家  ›  专栏  ›  技术社区  ›  dfrib

使用inout关键字:是通过引用或通过copy-in-copy-out(/call-by-value-result)传递的参数

  •  6
  • dfrib  · 技术社区  · 10 年前

    问题: 根据以下信息和讨论: inout 参数 通过引用传递 通过拷贝输入拷贝输出 ?


    基于以下SO线程 输入输出 关键字是 通过引用传递 :

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


    然而,根据苹果的文档(据我所知) 输入输出 关键字被传递 复制进复制出 (或 按值调用结果 )

    输入输出参数的传递方式如下:

    当调用该函数时, 参数的值被复制 在里面 函数的主体, 副本已修改 。当函数 返回, copys值被分配给原始参数 这 行为被称为 复制进复制出 或按值调用结果。。。

    …通过将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
    

    这个例子意味着 输入输出 参数确实是通过引用传递的(如上面两个链接的SO线程所示)。因为我们在inout参数前面加了一个与号( & )这确实“感觉”合乎逻辑。

    尽力确保我的例子具有代表性——因为这里 输入输出 参数 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)
    

    好啊 我的本地结构 在这个例子中,函数实际上是局部的,因此通过值传递(引擎盖后面没有引用)。


    结果: 鉴于以上, 输入输出 参数通过引用传递?

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

    1. 我是否误解了 输入输出 在苹果语言文档中,它是否可以解释为“通过引用传递”?
    2. 或者,我的例子仍然不能代表这个案例吗?
    1 回复  |  直到 9 年前
        1
  •  2
  •   vadian    10 年前

    《语言参考》中接下来的两段对其进行了更详细的描述:

    输入输出参数

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

    作为优化,当参数是存储在物理 内存中的地址,在和中使用相同的内存位置 在函数体外部。 优化的行为称为调用 参考 ; 它满足中副本的所有要求 复制出模型,同时消除复制的开销。 不依赖 复制入复制出与调用入的行为差异 参考

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

    推荐文章