结构体与类的本质区别
- 结构体是值类型(枚举也是值类型),类是引用类型(指针类型) 值类型存储在栈空间,引用类型存储在堆空间
// 类
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()方法在内存中的存储结构

- point结构体是值类型,在内存中存储的是值
- size类是引用类型,在内存中存储的是Size对象的内存地址

- 前边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
}
栈空间的存储结构如下所示

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
}
内存中的存储结构如下图所示

引用类型的赋值操作
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)
内存中的结构如下图所示

对象堆空间申请过程
在Swift中,创建类的实例对象,要向堆空间申请内存,大概流程如下
- Class._allocating_init()
- libswiftCore.dylib:swift_allocObject
- libswiftCore.dylib:swift_slowAlloc
- libsystem_malloc.dylib:malloc
在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