swift inout参数是变量还是指针?

Is swift inout parameter a variable or a pointer?

我觉得在下面的代码中使用 swift inout 参数有点迷茫:

var shouldContinue: Bool = true

func doSomeWork1(shouldContinue: inout Bool)
{
    while shouldContinue
    {
        // ERROR: the compiler wants: doSomeWork2(shouldContinue: &shouldContinue)
        doSomeWork2(shouldContinue: shouldContinue)
    }
}

func doSomeWork2(shouldContinue: inout Bool)
{
    while shouldContinue
    {

    }
}

为什么编译器需要 doSomeWork2(shouldContinue: &shouldContinue) 而不是 the compiler wants: doSomeWork2(shouldContinue: shouldContinue)shouldContinue 是否已经是 doSomeWork1() 范围内的指针???

作为指针只是输入输出参数优化过程的副作用。它们实际上以不同的方式工作,使用 copy-in-copy-out 行为。所以在函数内部,参数就像常规变量一样对待,而不是指针。如果你将它传递给另一个接受 inout 参数的函数,你必须这样标记它。

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. 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. Write your code using the model given by copy-in copy-out, without depending on the call-by-reference optimization, so that it behaves correctly with or without the optimization.

In-Out Parameters

来自:Matt Neuburg 的书“iOS 13 个编程基础知识 Swift。” :

如果我们希望函数改变传递给它的参数的原始值,我们必须执行以下操作:

  • 我们要修改的参数类型必须声明inout.
  • 我们在调用函数的时候,保存要修改的值的变量必须用var声明,而不是let。
  • 我们必须传递其地址,而不是将变量作为参数传递 。这是通过在其名称前加上一个符号 (&) 来完成的。

我们的 removeCharacter(_:from:) 现在看起来像这样:

 func removeCharacter(_ c:Character, from s: inout String) -> Int {
  var howMany = 0
  while let ix = s.firstIndex(of:c) {
    s.remove(at:ix)
    howMany += 1
  }
 return howMany
}

我们对 removeCharacter(_:from:) 的调用现在看起来像这样: 变量 s = "hello" 让结果 = removeCharacter("l", from:&s) 调用后结果为2,s为"heo"。当我们将它作为 from: 参数传递时,请注意名称 s 之前的 & 符号。这是必需的;如果你省略它,编译器会阻止你。我喜欢这个要求,因为它迫使我们明确地向编译器和我们自己承认,我们将要做一些有潜在危险的事情:作为副作用,我们让这个函数修改了它自身之外的值。