闭包
闭包:一个函数和它所捕获的变量\常量环境组合起来,称为闭包
(一般它捕获的是外层函数的局部变量\常量)
- 可以把闭包想象成是一个类的实例对象
- 捕获的局部变量\常量就是对象的成员(存储属性)
- 组成闭包的函数就是类内部定义的方法
func getFn() -> (Int) -> Int {
var num = 0
return {
num += $0;
return num;
}
}
var fn = getFn() // malloc堆地址 将外部变量num存入
print(fn(1)) // 1
print(fn(2)) // 3
print(fn(3)) // 6
print(fn(4)) // 10
print(getFn()(1)) // 1 malloc
print(getFn()(2)) // 2 malloc
print(getFn()(3)) // 3 malloc
print(getFn()(4)) // 4 malloc
反汇编查看
-
将局部变量注掉,观察运行过程中并没有调用 swiftallocObject,并没有向堆空间申请地址。
-
使用局部变量时,闭包内部需要捕获外部的局部变量/常量,存储在堆空间中。 打印 rax,获取闭包在堆空间保存变量的地址的位置。
-
将断点打在 num 变化处,去堆空间地址中查看存储数值是否发生改变,若能对应得上,则证明猜想正确。
练习
typealias Fn = (Int) -> (Int, Int)
func getFns() -> (Fn, Fn) {
// 分别创建两个地址保存,但数据是共用的
var num1 = 0 // malloc num1
var num2 = 0 // malloc num2
func plus(_ i: Int) -> (Int, Int) {
num1 += i
num2 += i << 1 // *2
return (num1, num2)
}
func minus(_ i: Int) -> (Int, Int) {
num1 -= i
num1 -= i << 1
return (num1, num2)
}
return (plus, minus)
}
// 把闭包想象成是一个类的实例对象,捕获的局部变量\常量就是对象的成员
let (p, m) = getFns()
print(p(5)) // (5, 10)
print(m(4)) // (1, 2)
print(p(3)) // (4, 8)
print(m(2)) // (2, 4)
网友评论