【问题标题】:Swift: how closure captures variables of value type?Swift:闭包如何捕获值类型的变量?
【发布时间】:2023-03-12 03:32:01
【问题描述】:

看看下面的代码sn-p

struct Person{
  var name: String
  let surname: String
  var closure: (()->())?
   init(name: String, surname: String){
      self.name = name
      self.surname = surname
    
   }
}

var person = Person(name: "John",  surname: "Lennon")
let cl = {
   print(person.name)
}

person.name = "Bill"
cl()
print(person.name)

上面sn-p的输出是

Bill
Bill

有人能解释一下这是怎么发生的吗?我认为由于闭包是引用类型,Person 是值类型,所以当创建闭包时,它会获得自己的 Person 副本(因为值类型是在传递时复制的),所以修改外部 Person 不应该影响由闭包捕获的Person,但它似乎不能以这种方式工作。我是 swift 和 value 类型的新手,所以请不要太用力地判断我的问题。
谢谢
我知道我们可以使用捕获列表显式捕获值变量,在这种情况下修改外部变量不会影响捕获的变量。这个问题是没有的。问题在于我认为即使没有明确捕获它也应该具有相同的方式

【问题讨论】:

标签: swift struct closures value-type


【解决方案1】:

只有当你像这样显式地将变量传递给闭包时,你所期望的行为才会起作用:

var person = Person(name: "John",  surname: "Lennon")
let cl: (Person) -> () = { person in
    print(person.name)
}
cl(person)
person.name = "Bill"
cl(person)

当您在闭包中隐式捕获变量时,该变量始终通过引用传递。如果要按值捕获变量,则需要显式传入。

【讨论】:

  • 感谢您的回复。你能解释更多关于that variable is always passed by reference的信息吗?既然是值类型,如何传递 ref ?这是否意味着在这种情况下值类型是 Boxed 以某种方式传递 ref?
  • @jonnyB_5531 值类型仍然有一个存储它们的内存地址(当通过引用传递时,指向该内存地址的指针本质上是传递的)。想想值类型的 inout 参数是如何工作的。
  • 在这种情况下“inout”是正确的例子吗?据我所知,“inout”遵循copy-in-copy-out规则,所以当变量作为inout传递时,你仍然会得到它的副本,可以在函数内部修改,然后分配到相同的内存位置
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-28
  • 1970-01-01
  • 2018-01-18
  • 1970-01-01
相关资源
最近更新 更多