Swift - 闭包捕获值原理分析

简介: 先说原理本质:编译器在堆上开辟空间,存放了捕获的值

先说原理本质:


编译器在堆上开辟空间,存放了捕获的值


看代码和打印:

func makeIncriementer() -> () -> Int {
    var runnintTotal = 10
    func incriementer() -> Int {
        runnintTotal += 1
        return runnintTotal
    }
    return incriementer
}
let makeInc = makeIncriementer()
print(makeInc())
print(makeInc())
print(makeInc())


打印输出:

11
12
13


将代码编译成SIL源码查看


附: 编译指令:swiftc -emit-sil main.swift | xcrun swift-demangle >> ./main.sil

// makeIncriementer()
sil hidden @main.makeIncriementer() -> () -> Swift.Int : $@convention(thin) () -> @owned @callee_guaranteed () -> Int {
bb0:
  %0 = alloc_box ${ var Int }, var, name "runnintTotal" // users: %8, %7, %6, %1
  %1 = project_box %0 : ${ var Int }, 0           // user: %4
  %2 = integer_literal $Builtin.Int64, 10         // user: %3
  %3 = struct $Int (%2 : $Builtin.Int64)          // user: %4
  store %3 to %1 : $*Int                          // id: %4
  // function_ref incriementer #1 () in makeIncriementer()
  %5 = function_ref @incriementer #1 () -> Swift.Int in main.makeIncriementer() -> () -> Swift.Int : $@convention(thin) (@guaranteed { var Int }) -> Int // user: %7
  strong_retain %0 : ${ var Int }                 // id: %6
  %7 = partial_apply [callee_guaranteed] %5(%0) : $@convention(thin) (@guaranteed { var Int }) -> Int // user: %9
  strong_release %0 : ${ var Int }                // id: %8
  return %7 : $@callee_guaranteed () -> Int       // id: %9
} // end sil function 'main.makeIncriementer() -> () -> Swift.Int'


通过源码可以看到,编译器将runnintTotal这个变量是通过

%0 = alloc_box ${ var Int }, var, name "runnintTotal" // users: %8, %7, %6, %1创建的


关于alloc_box 本质是在堆上开辟内存空间,存储了metadata、refrcount、value


image.png

WX20211209-172855@2x.png


参照:


SIL开发文档


SIL开发文档-allocBox


The LLVM Compiler Infrastructure


Swift的高级中间语言:SIL



相关文章
|
21天前
|
Swift UED
Swift 中使用闭包处理事件
【10月更文挑战第20天】使用闭包来处理事件在 Swift 编程中是一种非常常见和有效的方式。它提供了简洁、灵活和高效的解决方案,使我们能够更轻松地实现各种交互功能。通过深入理解闭包的原理和应用方法,我们可以更好地利用闭包来处理各种事件,提升应用的用户体验和开发效率。
|
12天前
|
存储 Swift iOS开发
Swift 闭包
10月更文挑战第28天
18 0
|
4月前
|
存储 Swift
Swift之struct二进制大小分析
【7月更文挑战第18天】Swift 中 `struct` 的二进制大小分析: `struct` 作为值类型, 其内存布局和大小由成员变量决定。基本类型如 `Int`, `Double`, `Bool` 存储大小固定; 复合类型如数组大小取决于元素数量及类型。示例 `struct` 包含 `Int`, `Double`, `Bool`, 和 `[String]`。`Int` 和 `Double` 各占 8 字节, `Bool` 占 1 字节, 数组大小根据字符串存储开销变化。还需考虑内存对齐以优化访问效率。综上, 分析 `struct` 大小需考量多种因素。
|
6月前
|
存储 API Swift
【Swift开发专栏】Swift函数与闭包的实战应用
【4月更文挑战第30天】本文介绍了 Swift 中函数和闭包的实战应用。首先,函数的基本使用包括定义、参数与返回值、函数类型以及高级技巧如嵌套函数。接着,讨论了闭包的语法,包括无名函数、作为函数参数、简写形式和尾随闭包。最后,展示了函数和闭包在实战中的应用,如排序过滤集合和处理异步任务的回调。
49 0
|
6月前
|
存储 Swift
Swift 语言:什么是闭包(Closure)?它们与函数的区别是什么?
Swift 语言:什么是闭包(Closure)?它们与函数的区别是什么?
128 1
|
6月前
|
存储 Swift
Swift中,函数和闭包
Swift中,函数和闭包
74 1
|
Swift
swift 闭包简写实际参数名$0、$1等理解
swift 闭包简写实际参数名$0、$1等理解
108 0
|
存储 编译器 Swift
Swift5.0 - day4-闭包、属性、方法、下标
Swift5.0 - day4-闭包、属性、方法、下标
323 0
Swift5.0 - day4-闭包、属性、方法、下标
|
Swift
Swift5.1—闭包的循环强引用
Swift5.1—闭包的循环强引用
225 0
Swift5.1—闭包的循环强引用
|
存储 编译器 开发者
Swift-进阶 09:闭包(二)逃逸闭包 & 非逃逸闭包
Swift-进阶 09:闭包(二)逃逸闭包 & 非逃逸闭包
530 0
Swift-进阶 09:闭包(二)逃逸闭包 & 非逃逸闭包