swift04-值类型 & 引用类型

228 阅读3分钟

Swift 进阶之路 文章汇总

前言:

上篇文章分享了属性属性观察者,本篇文章主要分析swift中的数据类型:

  • 值类型
  • 引用类型

在分析数据类型前,先了解下内存的存储的5大区域,按照地址排列: 栈区 -> 堆区 -> 全局静态区 -> 常量区 -> 代码区

其中栈区 是从高地址低地址分配空间,堆区全局静态区常量区代码区 都是从低地址高地址分配空间,开发中的溢出是指堆栈溢出,可以理解为栈区与堆区边界碰撞的情况

值类型

有了以上对内存的认知,引入什么是值类型.

在xcode中定义一个方法,并调用

查看age的内存情况,从图中可以看出,栈区直接存储的是,断点继续运行

查看age2的情况,从下图中可以看出,age2的赋值相当于将age中的值拿出来,赋值给了age2。其中ageage2 的地址 相差了8字节,从这里可以说明栈空间是连续的、且是从高到低

由此可见值类型 特点

  1. 地址中存储的是
  2. 值类型的传递过程中,相当于传递了一个副本,也就是所谓的深拷贝
  3. 值传递过程中,并不共享状态

结构体

创建结构体

更改结构体属性的值

结构体的SIL分析

进入init方法

SIL文件中,我们查看结构体的初始化方法,可以发现只有init,而没有malloc,在其中看不到任何关于堆区的分配.所以结构体是值类型,且结构体的地址就是第一个成员的内存地址

引用类型

 创建一个结构体和类打印内存进行对比

查看内存存储情况

SIL源码分析

  • 查看结构

  • 查看main函数结构

  •  查看初始化方法      

断点内存调试

  • 打印内存地址

  • 查看内存存储情况

关键字mutaing

  • 现象分析

通过结构体定义一个,主要有push、pop方法,此时我们需要动态修改栈中的数组

定义一个结构体,并添加个调用方法

查看SIL源码

修改方法

系统不报错,但是数据没有添加到数组中,原因是因为虽然我们将它转成了变量但是结构体是值传递,修改方法里面的结构体不会对外面有影响

查看SIL源码

  • 查看mutating的本质

根据**错误提示**,应使用**mutaing关键字**进行修饰

查看mutating的本质

由此可看出push添加mutating(只用于值类型)后,本质上是给值类型函数添加了inout关键字,相当于在值传递的过程中,传递的是引用(即地址)

inout关键字

在函数的声明中,默认的参数都是不可变的,如果想要直接修改,需要给参数加上inout关键字

  • 总结
  1. 结构体中的函数如果想修改其中的属性,需要在函数前加上mutating,而类则不用

  2. mutating本质也是加一个 inout修饰的self

  3. Inout相当于取地址,可以理解为地址传递,即引用

  4. mutating修饰方法,而inout 修饰参数

总结

  • 值类型就是地址中存储的是

  • 值类型的传递,传递的是,类似于深拷贝

  • 引用类型就是地址中存储的是内存中所在地址

  • 内存中所在地址存储的才是值

  • 值类型开辟的空间在中,能快速调用

  • 引用类型开辟的空间在