美文网首页
Swift中枚举的内存布局

Swift中枚举的内存布局

作者: lieon | 来源:发表于2020-11-14 00:15 被阅读0次

    枚举

    枚举的基本用法

    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
             }
         }
    

    相关文章

      网友评论

          本文标题:Swift中枚举的内存布局

          本文链接:https://www.haomeiwen.com/subject/tdkvbktx.html