gpt4 book ai didi

Swift:闭包是否引用常量或变量?

转载 作者:搜寻专家 更新时间:2023-10-30 23:14:00 24 4
gpt4 key购买 nike

我知道有几个相关问题,而且我可以在 Internet 上找到很多帖子。但是,我无法理解闭包可以保存引用这一事实。在引用类型的情况下,它是完全常见且非常合理的,但是值类型呢,包括 structenum?请参阅此代码。

let counter: () -> Int
var count = 0
do {
counter = {
count += 1
return count
}
}
count += 1 // 1
counter() // 2
counter() // 3

我们可以通过两种方式访问​​值类型count。一种是直接使用count,另一种是通过闭包counter。但是,如果我们写

let a = 0
let b = a

,在内存中b当然和a有不同的区域,因为它们是值类型。而这种行为是值类型不同于引用类型的一个显着特征。然后回到闭包主题,闭包具有对值类型的变量或常量的引用。

所以,我可以说在闭包捕获值的情况下,我们不能对值类型有任何引用的值类型的特性被改变了吗?对我来说,捕获对值类型的引用是非常令人惊讶的,同时我上面展示的经验也表明了这一点。

你能解释一下吗?

最佳答案

我认为混淆是因为对值类型与引用类型的思考过于认真。这与此关系不大。让我们将数字设为引用类型:

class RefInt: CustomStringConvertible {
let value: Int
init(value: Int) { self.value = value }
var description: String { return "\(value)" }
}

let counter: () -> RefInt
var count = RefInt(value: 0)
do {
counter = {
count = RefInt(value: count.value + 1)
return count
}
}
count = RefInt(value: count.value + 1) // 1
counter() // 2
counter() // 3

这感觉有什么不同吗?我希望不是。都是一样的,只是引用而已。这不是值(value)/引用的东西。

关键是,正如您所注意到的,闭包捕获了变量。不是变量的值,也不是变量指向的引用的值,而是变量本身)。因此,在捕获该变量的所有其他地方(包括调用者)都可以看到闭包内变量的更改。这在 Capturing Values 中有更全面的讨论。 .

如果您有兴趣,可以更深入一点(现在我将介绍一些可能超出您现在关心的技术细节):

闭包实际上有一个对变量的引用,并且它们所做的更改会立即发生,包括调用didSet等。这与inout参数不同,它赋值只有当他们返回时,他们的原始上下文的值(value)。你可以这样看:

let counter: () -> Int
var count = 0 {
didSet { print("set count") }
}

do {
counter = {
count += 1
print("incremented count")
return count
}
}

func increaseCount(count: inout Int) {
count += 1
print("increased Count")
}

print("1")
count += 1 // 1
print("2")
counter() // 2
print("3")
counter() // 3

increaseCount(count: &count)

这打印:

1
set count
2
set count
incremented count
3
set count
incremented count
increased Count
set count

请注意“set count”总是在“incremented count”之前但在“increased count”之后。这表明闭包实际上指的是它们捕获的同一个变量(不是值或引用;变量),以及为什么我们称它为闭包的“捕获”,而不是“传递”给函数。 (当然,您也可以“传递”给闭包,在这种情况下,它们的行为与那些参数上的函数完全一样。)

关于Swift:闭包是否引用常量或变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44642073/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com