Files
SwiftStudy/08 类.playground/Resources
2022-01-07 11:14:35 +08:00
..
2022-01-07 11:14:35 +08:00

结构体与类的本质区别

  • 结构体是值类型(枚举也是值类型),类是引用类型(指针类型) 值类型存储在栈空间,引用类型存储在堆空间
// 类
class Size {
    var width = 1
    var height = 2
}
// 结构体
struct Point {
    var x = 3
    var y = 4
}
// 方法体
func test() {
    var size = Size()
    var point = Point()
}

test()方法在内存中的存储结构

jiulinxiri_20220106223910.png
  • point结构体是值类型在内存中存储的是值
  • size类是引用类型在内存中存储的是Size对象的内存地址
jiulinxiri_20220106224431.png
  • 前边16个字节存储的是指向类型信息以及引用计数
  • 后边的16个字节存储的是成员变量

值类型

值类型赋值给var,let 或者函数参数传参,是直接将所有的内容拷贝一份。

类似于对文件进行copy、paste操作产生了全新的文件副本。属于深拷贝deep copy

struct Point { 
  var x: Int 
  var y: Int
}
func test() {
var p1 = Point(x: 10, y: 20) 
var p2 = p1
}

栈空间的存储结构如下所示

jiulinxiri_20220107093427

p1和p2成员变量之间的赋值操作没有任何影响

值类型的赋值操作

var a1 = [1, 2, 3] 
var a2 = a1
a2.append(4) 
a1[0] = 2
print(a1) // [2, 2, 3] 
print(a2) // [1, 2, 3, 4]

在Swift标准库中为了提升性能String、Array、Dictionary、Set采取了Copy On Write的技术

  • 比如仅当有“写”操作时,才会真正执行拷贝操作

不需要修改的,尽量定义成 let

引用类型

引用赋值给 var,let或者给函数传参,是将内存地址拷贝一份。

类似于制作文件替身快捷方式、链接指向同一文件属于浅拷贝shallow copy

class Size {
  var width: Int
  var height: Int
  init(width: Int, height: Int) { 
    self.width = width
    self.height = height 
  }
}
func test() {
  var s1 = Size(width: 10, height: 20) 
  var s2 = s1
}

内存中的存储结构如下图所示

jiulinxiri_20220107102828

引用类型的赋值操作

class Size {
  var width: Int 
  var height: Int
  init(width: Int, height: Int) {
    self.width = width 
    self.height = height
	} 
}
var s1 = Size(width: 10, height: 20) 
s1 = Size(width: 11, height: 22)

内存中的结构如下图所示

jiulinxiri_20220107104836

对象堆空间申请过程

在Swift中创建类的实例对象要向堆空间申请内存大概流程如下

  • Class._allocating_init()
  • libswiftCore.dylibswift_allocObject
  • libswiftCore.dylibswift_slowAlloc
  • libsystem_malloc.dylibmalloc

在Mac、iOS中的malloc函数分配的内存大小总是16的倍数 通过 class_getInstanceSize 可以得知:类的对象至少需要占用多少内存

class Point	{  var x = 11
  var test = true
  var y = 22
}
var p = Point()  class_getInstanceSize(type(of: p)) // 40  
class_getInstanceSize(Point.self) // 40