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

相关推荐
2501_916008893 小时前
全面介绍Fiddler、Wireshark、HttpWatch、SmartSniff和firebug抓包工具功能与使用
android·ios·小程序·https·uni-app·iphone·webview
AI架构全栈开发实战笔记7 小时前
Eureka 在大数据环境中的性能优化技巧
大数据·ai·eureka·性能优化
Haha_bj7 小时前
Flutter ——flutter_screenutil 屏幕适配
android·ios
Haha_bj7 小时前
Flutter ——device_info_plus详解
android·flutter·ios
野生技术架构师11 小时前
SQL语句性能优化分析及解决方案
android·sql·性能优化
符哥200811 小时前
一套基于Swift+MVVM为基础的iOS App 开发框架
swift
山水域12 小时前
SKAdNetwork 6.0 深度实战:多窗口转化值(Conversion Value)建模与数据分层架构
ios
JavinLu13 小时前
ios 配置了代理且使用 chls.pro/ssl 下载不了证书,无法弹出下载证书的提示问题
网络协议·ios·ssl
l1t14 小时前
DeepSeek总结的PostgreSQL解码GIF文件SQL移植到DuckDB的性能优化方法
sql·postgresql·性能优化
数据知道14 小时前
PostgreSQL 性能优化:分区表实战
数据库·postgresql·性能优化