一文读懂 - 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 中合理使用值类型可显著提升性能。

相关推荐
牛巴粉带走17 分钟前
Flutter 构建失败:watchOS Target 类型无法识别的解决记录
flutter·ios·apple watch
程序员陆通2 小时前
MySQL索引底层原理与性能优化实践
数据库·mysql·性能优化
麦兜*2 小时前
Spring Boot 与 Ollama 集成部署私有LLM服务 的完整避坑指南,涵盖 环境配置、模型管理、性能优化 和 安全加固
java·spring boot·后端·安全·spring cloud·性能优化
无知的前端2 小时前
一文读懂 - Flutter (Dart) 对象内存分配深度解析
flutter·性能优化
游戏开发爱好者82 小时前
Fiddler中文版使用指南 提升开发流程的一站式抓包与调试体验
android·ios·小程序·https·uni-app·iphone·webview
杂雾无尘3 小时前
分享一个让代码更整洁的 Xcode 开发小技巧:设置文件目标平台
ios·swift·apple
桦说编程3 小时前
CompletableFuture 的第四种调用模式
java·性能优化·函数式编程
EndingCoder4 小时前
HTTP性能优化实战:解决高并发场景下的连接瓶颈与延迟问题
网络·网络协议·http·性能优化·高并发
wyiyiyi6 小时前
【目标检测】芯片缺陷识别中的YOLOv12模型、FP16量化、NMS调优
人工智能·yolo·目标检测·计算机视觉·数学建模·性能优化·学习方法