一文读懂 - 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 小时前
高轨航天器抗辐照MCU选型约束分析
单片机·嵌入式硬件·性能优化·机器人·安全性测试
行者963 小时前
OpenHarmony Flutter跨平台开发:树形视图组件的实践与性能优化
flutter·性能优化·harmonyos·鸿蒙
tiantian_cool16 小时前
Claude Code 四大核心技能使用指南
ios
持续升级打怪中18 小时前
Vue3 中虚拟滚动与分页加载的实现原理与实践
前端·性能优化
小宇的天下19 小时前
Calibre 3Dstack Flow Example(5-2)
性能优化
Tisfy19 小时前
网站访问耗时优化 - 从数十秒到几百毫秒的“零成本”优化过程
服务器·开发语言·性能优化·php·网站·建站
冰淇淋真好吃20 小时前
iOS实现 WKWebView 长截图的优雅方案
ios
Light6020 小时前
静默的范式转移:前端开发从“框架之战”步入“编译器之争”
性能优化·前端开发·服务端渲染·渐进式迁移·编译器时代
njsgcs20 小时前
Swift playground 网页刷新切换随机页面的网页查看器WebKit
swift
sophie旭1 天前
性能监控之首屏性能监控小实践
前端·javascript·性能优化