Swift Day06 值类型 引用类型 闭包

一、值类型、引用类型

1. 用 let 修饰 结构体实例的值类型类实例的引用类型 时,分别修改它们的成员变量,能编译通过吗?
  • 核心点:理解 let 修饰的实例,其内存是不可以改变的。
    木有警告信息的就代表能编译通过
2. 方法和函数的区别?类、枚举、结构体都能定义方法吗?
  • 方法和函数没区别,是同一个东西
  • 通常把定义在类、枚举、结构体内部的函数,叫做方法
3. 思考下面这个方法show,它的本质是什么?在代码段如何存储的?(非常重要)
class Point {
    var x = 11
    var y = 22
    func show() {
        print(x,y)
    }
}
var p = Point()
p.show()
  • 上面类中的 show 方法,最终会其实会转变成类似下面的函数,存储在代码段
func show(self: Point) {
  print(self.x, self.y)
}
4. 定义一个全局变量let a = 10,在底层机器码阶段,只知道 a 的地址上是一个存储着 10 这个数据,程序是怎么标记它是 Int 类型呢?(一个困扰很久的问题 )
  • 其实对于这个问题,我一开始就进入了误区。
  • 在机器码阶段,它根本不关心 a 的地址上存储的数据是什么类型的,也不会存储任何类型相关的信息(类型在编译阶段应该保证的事情,有个符号表
查阅资料`https://qastack.cn/software/380347/how-do-variables-in-c-store-their-type`
5. 我们如何证明函数和方法(类中定义的函数),都是存放在代码段呢?
示例代码
  • 我们如上图所示打三个断点,进入汇编调试,可以拿到show 、 show1 、 &a的地址值
  • 可以发现 &a 是全局常量,存放在全局区,地址值大于 show 和 show1
  • show 和 show1的地址值极其接近,所以大概率都存放在代码区

二、闭包

1. 在 Swift 中有两种方式定义函数,哪两种?
  • 闭包表达式
  • func
闭包函数
2. 闭包表达式通常用于参数传递,可以进行简写(理解下列简写过程)
闭包表达式简写过程
3. 尾随闭包表达式?为什么要有?如何简写?
  • 如果将一个很长的闭包表达式作为函数的最后一个参数,使用尾随闭包可以增强函数的可读性
  • 尾随闭包是一个被书写在函数调用括号外面(后面)的闭包表达式
尾随闭包
  • 如果闭包表达式是函数唯一实参,而且使用了尾随闭包的语法,那就不需要在函数名后边写圆括号
尾随闭包
4. 闭包(Closure)是什么?
  • 一个函数和它捕获的变量\常量环境组合起来,称为闭包
  • 一般指定义在函数内部的函数
  • 一般它捕获的是外层函数的局部变量\常量
5. 请问下面闭包输出是什么?
闭包
  • 输出:1 3 6 10 , 为什么呢?
  • num 被捕获会被拷贝到堆内存
6. 如何证明 num 被拷贝到了堆内存呢?
断点 1,没有形成闭包的情况
  • 获得以汇编代码的形式看断点代码:


    断点1的汇编,没有形成闭包的情况
  • 断点 2


    断点 2,有闭包的情况
  • 获得以汇编代码的形式看断点代码:


    断点 2 汇编,有闭包的情况
  • 对比断点 1断点 2的汇编,我们可以发现 断点 2 出现了 alloc 函数

  • alloc 函数往往意味着堆空间的开辟

  • 设置如下两个断点


    我们给代码设置如下两个断点
  • var num = 0 这句代码可以获取 num 分配的内存地址,通常放在 rax 寄存器中,然后我们取消这个断点

    获取 num 对象内的值

获取 堆内存中 num 对象的值
  • 然后我们四次过掉剩下的断点,分别进行打印,发现和我们猜想非常一致,num 的值也经历的 0 1 3 6 10的变化

  • 借此充分证明了 num 被拷贝到了堆内存中,也解答了这个打印结果的问题

7. 如果上题中的 num 变成全局变量,会捕获吗?
  • 不会进行捕获,找不到任何 alloc 相关的函数
  • 其实也没必要进行捕获,因为可以正常访问
8. 为什么可以把闭包想象成一个类的实例对象?
闭包 VS 类实例对象
9. 闭包闭包表达式有什么不同?
  • 闭包表达式:用于定义函数的方式之一
  • 闭包:一个函数和它捕获的变量\常量环境组合起来,称为闭包
10. 一道综合题,测试对闭包的理解,请说出输出值?
综合题
  • 输出:
答案

你可能感兴趣的:(Swift Day06 值类型 引用类型 闭包)