Swift中枚举的内存布局
2020-11-14 本文已影响0人
lieon
枚举
枚举的基本用法
enum Direction {
case north
case south
case east
case west
}
let dir: Direction = .north
关联值(Associated Values)
enum Score {
case points(Int)
case grade(String)
}
let score: Score = .points(3)
原始值(Raw Values)
- 枚举成员可以使用相同类型的默认值预先对应,这个默认值叫做:原始值
- 原始值不占用枚举变量的内存
enum Grade: String {
case perfect = "A"
case great = "B"
case good = "C"
case bad = "D"
}
隐式原始值(Implicitly Assigned Raw Values)
- 如果枚举的原始值类型是Int,String,Swift会自动分配原始值
enum Direction: String {
case north = "north"
case south = "south"
case east = "east"
case west = "west"
}
/// 等价于
enum Direction {
case north
case south
case east
case west
}
递归枚举(Recursive Enumeration)
indirect enum ArithExpr {
case number(Int)
case sum(ArithExpr, ArithExpr)
}
enum ArithExpr {
case number(Int)
indirect case sum(ArithExpr, ArithExpr)
}
MemoryLayout
- MemoryLayout可以获取到数据类型占用的内存大小
基础枚举内存大小为
- 系统分配1个字节
- 实际用到1个字节
- 按1个字节对接
enum TestEnum1 {
case test1
case test2
case test3
}
enum TestEnum2: Int {
case test1
case test2
case test3
}
var test = TestEnum1.test3
print(Mems.ptr(ofVal: &test))
print(Mems.size(ofVal: &test))
let stride = MemoryLayout<TestEnum1>.stride // 1
let size = MemoryLayout<TestEnum1>.size // 1
let alignment = MemoryLayout<TestEnum1>.alignment // 1
关联值枚举内存大小为(TestEnum3为例)
- 分配的内存大小为32个字节
- 实际用到的字节为25个字节
- 以8个字节对齐
// 01 00 00 00 00 00 00 00
// 02 00 00 00 00 00 00 00
// 03 00 00 00 00 00 00 00
// 01
// 分配了32个字节,但是只用到25个字节,前24个字节用来存储关联值,第25个字节用来存储成员值
var test = TestEnum3.test2(1, 2, 3)
// 01 00 00 00 00 00 00 00
// 02 00 00 00 00 00 00 00
// 03 00 00 00 00 00 00 00
// 00
test = .test1(1, 2, 3)
// 03 00 00 00 00 00 00 00
// 00 00 00 00 00 00 00 00
// 00 00 00 00 00 00 00 00
// 02
test = .test3(3)
// 01 00 00 00 00 00 00 00
// 00 00 00 00 00 00 00 00
// 00 00 00 00 00 00 00 00
// 03
test = .test4(true)
// 00 00 00 00 00 00 00 00
// 00 00 00 00 00 00 00 00
// 00 00 00 00 00 00 00 00
// 04
test = .test5
let stride = MemoryLayout<TestEnum3>.stride // 32
let size = MemoryLayout<TestEnum3>.size // 25
let alignment = MemoryLayout<TestEnum3>.alignment // 8
总结:
- 1个字节存储成员值
- N个字节存储关联值(N去最大case的关联值的个数),任何一个case的关联值共用这N个字节
- 只有1个case的无关联值枚举内存为0
- 单个case的关联值枚举内存关联值的内存大小 (因为就一个case,不需要存储值来区分)
- 原始值不占用内存大小(为什么?因为可以这样写)
var rawValue: Int {
switch self {
case .test1:
return 0
case .test2:
return 1
case .test3:
return 2
case .test4:
return 3
case .test5:
return 4
}
}