美文网首页
第七节 闭包二

第七节 闭包二

作者: 天明天 | 来源:发表于2021-02-02 14:18 被阅读0次

    一.闭包的内存

    1.闭包捕捉的num相当于 类的成员变量,闭包的方法,相当于类的实例方法。

    typealias Fu = (Int) - > Int
    
    func getFn() -> Fn {
    
    //局部变量,这里会分配堆空间 便于下面的函数捕获他
     var num = 0
    
      func plus(_ v1 : Int) ->Int{
       num += v1
       return  num
    
     } 
    
     return plus
    
    }  
    
    var fn1 = getFn()
    
    • 查看fn1的内存地址、以及内容一般的常用方法在这里不支持
    //打印普通变量地址,在这里含有函数,所以无法打印
    print(Mens.ptr(ofVal: &fn1))
    print(Mens.memStr(ofVal: &fn1))//打印普通对象内容
    
    
    • 借助汇编语言来做
    MemoryLayout.stride(ofValue: fn1)//占用多少字节
     //16 字节
    

    这里注意内存地址与内存地址的存储内容的区别(类似于房间编号跟房间里的人的区别)

    截屏2020-07-28 下午2.36.00.png
    • movq :每次向后移动8个字节,把rax赋值给后面的地址值
    • call 函数调用,后面接函数地址

    结论:

    • fun1 总共占用16个字节的内存
    • fun1 的前面 8 个字节放置的就是plus的函数地址
    • fun1 的后面的8个字节放置的是堆空间的地址值(房间里面放的是num的数值)
    • plus接受了两参数:i的值跟num的堆空间地址值
    • num的释放时机:arc下 没有强指针指向它时候 就会被释放。没有内存泄漏的风险。
    • num 的捕获时机:在调用return返回函数地址时捕获
    • 如果num是全局变量,plus函数是不会捕获num的值的,没有分配堆空间。
    func getFn() -> Fn {
    
    //局部变量,这里会分配堆空间 便于下面的函数捕获他
     var num = 0
    
      func plus(_ v1 : Int) ->Int{
       num += v1
       return  num
     } 
    
     num = 10
     return plus
    
    }  
    
    var fn1 = getFn()
    print(fn1(1)) //打印结果是:11
    
    

    注意:这里print(fn1(1)) //打印结果是:11。这里捕获的变量值是10,而不是0。捕获的时机是在return返回函数的时候

    练习1.
    截屏2020-07-28 下午3.28.28.png
    这里:i << 1 相当于 i * 2
    
    let (p,m) = getFuns()
    print(p(6))   // (6,12)
    print(m(5))  // (1,2)
    print(p(3))  // (5,10)
    print(m(2))  //(2,4)
    
    
    
    • getFun 返回 两个函数组成的元组,
    • 打印结果说明,这里 num1 跟num2 都是同一份,累计加减的结果。两个函数共享num1、mum2,捕获的变量相当于成员变量。
    • 类似下面的结构:
    截屏2020-07-28 下午3.48.27.png
    • 元组这里面的元素能直接拿出来用,这里p = plus,m = minus。这里num1 跟 num2 都只是分配了 一次堆空间。
    练习2.
    var funs : [() -> int] = []
    
    for i in 1...3{
    
       funs.append { i } // 尾随闭包的简写
      /*
       相当于:
    
       func myFunc () -> Int {
       
            return i
    }
    funs.append{ myFunc}
    */
    }
    
    for f in funs {
    
    print(''\(f())'')//打印的是函数 // 打印数值:1、2、3
    
    }
    
    类比: 截屏2020-07-28 下午4.04.47.png

    2. 注意:

    截屏2020-07-28 下午4.08.38.png

    3. 自动闭包

    截屏2020-07-28 下午4.17.31.png
    • 这里 v2:变成函数 的目的是,当第一个条件满足时候,不在运行后面的函数。

    如果这样写 getFirstPositive(_ v1:Int , _ v2: Int) -> Int{ return v1 > 0 ? v1 : v2}, 即使是v1 > 0, v2函数 仍然还是会调用。上面的写法是一种优化。

    @autoclosure() 自动闭包:

    截屏2020-07-28 下午4.24.45.png
    • 会自动将 参数20 生成闭包表达式。如果不写@autoclosure() 则写法为:getFirstPositive(10,{20})
    • @auticlosure () -> Int : 只支持 无参数的,并且有返回类型的闭包、
    • 其他说明:


      截屏2020-07-28 下午6.34.13.png
    截屏2020-07-28 下午6.27.42.png
    • @autoclosure 可以构成函数的重载;

    相关文章

      网友评论

          本文标题:第七节 闭包二

          本文链接:https://www.haomeiwen.com/subject/oxqtrktx.html