一文读懂 - Swift 和 Objective-C 创建对象时内存分配机制

在 iOS 开发中,Swift 和 Objective-C 创建对象时内存分配机制有显著差异。以下从底层原理、内存布局和实际分配角度详细分析:


一、Swift 对象内存分配

1. 核心特点

  • 最小分配单位 :Swift 对象默认最小分配 16 字节(64 位系统)

  • 内存布局

    swift

    复制代码
    | 8 字节 Metadata 指针 | 8 字节 RefCount(引用计数) | 实例变量... |
  • 空类(无属性)实例:固定 16 字节(Metadata + RefCount)

2. 内存增长规则

  • 属性增加 :每新增一个属性,按 8 字节对齐增长
  • 继承影响:父类属性优先布局,子类属性在后

3. 验证示例

swift

php 复制代码
class EmptyClass {} // 空类
print(class_getInstanceSize(EmptyClass.self)) // 输出:16

class MyClass {
    var id: Int = 0     // Int = 8 字节
    var flag: Bool = true // Bool = 1 字节(对齐到 8)
}
print(class_getInstanceSize(MyClass.self)) // 输出:32

计算过程

  • Metadata 指针:8 字节
  • RefCount:8 字节
  • id: Int:8 字节
  • flag: Bool:实际 1 字节 → 对齐填充后占 8 字节
  • 总计:8 + 8 + 8 + 8 = 32 字节

💡 系统实际调用 malloc 时可能分配 32/48/64 字节(系统内存块粒度),但对象自身仅使用对齐后的部分。


二、Objective-C 对象内存分配

1. 核心特点

  • 最小分配单位 :固定包含 isa 指针(8 字节

  • 内存布局

    objc

    复制代码
    | 8 字节 isa 指针 | 实例变量... |
  • 空类(继承自 NSObject)实例:8 字节 (仅 isa

2. 内存增长规则

  • 属性/IVars :按声明顺序排列,遵循 8 字节对齐
  • 无额外 RefCount:引用计数存储在全局 Side Table

3. 验证示例

objc

less 复制代码
@interface EmptyObjCClass : NSObject
@end
@implementation EmptyObjCClass
@end
NSLog(@"%zu", class_getInstanceSize([EmptyObjCClass class])); // 输出:8

@interface MyObjCClass : NSObject
@property (nonatomic, assign) NSInteger id; // long = 8 字节
@property (nonatomic, assign) BOOL flag;    // BOOL = 1 字节
@end
NSLog(@"%zu", class_getInstanceSize([MyObjCClass class])); // 输出:24

计算过程

  • isa 指针:8 字节
  • id: NSInteger:8 字节
  • flag: BOOL:实际 1 字节 → 对齐填充后占 8 字节
  • 总计:8 + 8 + 8 = 24 字节

💡 系统通过 alloc 分配时实际调用 malloc_zone_calloc,可能分配 16/32 字节 的内存块。


三、关键差异对比

特性 Swift Objective-C
元数据指针 Metadata (8 字节) isa (8 字节)
引用计数存储 对象内嵌 RefCount (8 字节) 全局 Side Table
空类最小大小 16 字节 8 字节
内存对齐 8 字节对齐 8 字节对齐
继承影响 父类属性优先布局 父类属性优先布局
系统分配实际大小 16/32/48 字节(内存块粒度) 16/32 字节(内存块粒度)

四、底层原理深入

1. Swift 的 RefCount 设计

  • 内嵌在对象头部的 Inline RefCount
  • 支持 强引用/弱引用计数 快速操作
  • 溢出时降级到 Side Table

2. Objective-C 的 isa 优化

  • isa 指针使用 non-pointer isa
  • 低比特位存储:引用计数标志、析构状态等
  • 节省全局表空间,提高访问效率

3. 系统分配策略

  • 实际调用 malloc_size 返回的大小总是 16 的倍数

  • 示例:

    swift

    scss 复制代码
    let obj = MyClass()
    print(malloc_size(Unmanaged.passUnretained(obj).toOpaque())) 
    // 可能输出:48(实际分配) vs 32(对象自身)

五、优化建议

  1. 减少小对象创建:尤其 Swift 有 16 字节最小开销

  2. 属性顺序优化

    swift

    kotlin 复制代码
    // 劣:占 40 字节(8+1 → 对齐后 8+8)
    class Bad {
        var a: Int8 = 0
        var b: Int = 0
    }
    
    // 优:占 24 字节(8+8 → 对齐后 16)
    class Good {
        var b: Int = 0
        var a: Int8 = 0
    }
  3. 值类型优先 :结构体(struct)无额外开销,栈分配


总结

  • Swift 对象:基础成本更高(16 字节起),适合复杂对象
  • Objective-C 对象:更轻量(8 字节起),但依赖全局表
  • 实际分配 :系统总是分配 ≥ 计算大小 的内存块(16 字节粒度)

理解这些差异有助于优化内存敏感场景(如高频创建对象),在 Swift 中合理使用值类型可显著提升性能。

相关推荐
如此风景1 小时前
Swift异步详解
swift
zzu123zsw2 小时前
第13章 Jenkins性能优化
运维·性能优化·jenkins
4z332 小时前
Jetpack Compose重组优化:机制剖析与性能提升策略
性能优化·android jetpack
HarderCoder2 小时前
强制 SwiftUI 重新渲染:`.id()` 这把“重启键”你用对了吗?
swift
HarderCoder3 小时前
Swift 6.2 新语法糖:在字符串插值里直接给 Optional 写默认值
swift
在下历飞雨3 小时前
AI+Kuikly自研DSL初体验:让UI开发更简洁优雅
ios·vibecoding
zzywxc7873 小时前
深入探讨AI三大领域的核心技术、实践方法以及未来发展趋势,结合具体代码示例、流程图和Prompt工程实践,全面展示AI编程的强大能力。
人工智能·spring·机器学习·ios·prompt·流程图·ai编程
DemonAvenger3 小时前
分库分表实战:应对数据增长的扩展策略
数据库·sql·性能优化
HarderCoder3 小时前
窥探 `@Observable` 的“小黑盒”:private 属性到底会不会被观察?
swift
zzywxc7873 小时前
AI 在金融、医疗、教育、制造业等领域有着广泛的应用,以下是这些领域的一些落地案例
人工智能·python·spring cloud·金融·swift·空间计算