Swift 闭包2

闭包尽量选择非逃逸闭包

函数是引用类型

  func addTwoInts(_ a: Double, _ b: Double) -> Double {

       return a + b

   }

var a = addTwoInts

var b = a

函数内存地址

函数的内存结构

1. 函数类型 type(of: a)

2.unsafeBitCast 指针转换

struct TargetFunctionTypeMetadata{

    var kind: Int

    var flags: Int

    func numberArguments() -> Int{

        return self.flags & 0x0000FFFF

    }

}

let type = type(of: a)

let functionType = unsafeBitCast(type as Any.Type, to: UnsafeMutablePointer.self) print(functionType.pointee.numberArguments()) // 2

闭包

闭包的本质

{ i8*, %swift.refcounted* }

闭包的执行地址  + 捕获变量堆空间的地址

1. Box 代表一个实例对象

2. HeapObject实例对象的metadata 和引用计数

3.Box 中的value 捕获的值

struct ClosureData{

    var ptr: UnsafeRawPointer // 闭包的执行地址

    var capatureValue: UnsafePointer> //  捕获变量堆空间的地址

}

struct HeapObject{   

    var metadata: UnsafeRawPointer   

    var refcount1: Int32   

    var refcount2: Int32

}

struct Box{   

    var object: HeapObject   

    var value: T

}

1. NoMeanStruct的内存地址和结构体第一个属性的内存地址是一样的,所以结构体NoMeanStruct的地址就是闭包的地址

struct NoMeanStruct{

   var f: () -> Int

}

    var a = 10

      var f = NoMeanStruct {

         a+= 30

         return a

      }

      var ptr = UnsafeMutablePointer<NoMeanStruct>.allocate(capacity: 1)

      ptr.initialize(to: f)

//      ptr[0] = f

      defer {

         ptr.deinitialize(count: 1)

         ptr.deallocate()

      }

      var ctx = ptr.withMemoryRebound(to: ClosureData>.self, capacity: 1) {

         return $0.pointee

      }

print(ctx)


闭包本质

1. 第一个打印出结果, 闭包的本质是闭包的执行地址  + 捕获变量堆空间的地址

2.第二个 lldb,看出ptr 是闭包的执行地址

3.第三个lldb,看出object是个堆地址

.ll 文件简单语法

*指针类型

[ x  ] 数组

{..., ...} 结构体

局部变量  var runningTotal = 10 

func makeIncrementer() -> () -> Int {

    var runningTotal = 10  //局部变量

    func incrementer() -> Int {

        runningTotal+= 1

        return runningTotal

    }

    return incrementer

}

let incr = makeIncrementer()

解析成.ll 文件

define i32 @main(i32 %0, i8** %1) #0 {

entry:

...

  %3 = call swiftcc { i8*, %swift.refcounted* } @"$s4main15makeIncrementerSiycyF"()

  ...

}

makeIncrementer() 返回  { i8*, %swift.refcounted* }  一个结构体,里面2个指针

%swift.refcounted = type { %swift.type*, i64 }

%swift.type = type { i64 }

推断出闭包是一个{ i8*,  type { type { i64 }, i64 }}


逃逸闭包

延长闭包的生命周期

逃逸闭包在函数内部异步执行或者被属性存储


非逃逸闭包

不会产生循环引用,函数作用域内释放  

编译器更多性能优化 (retain, relsase) 

上下文的内存保存再栈上,不是堆上 

你可能感兴趣的:(Swift 闭包2)