值类型
- 在栈上创建,创建速度快
- 内存占用小。整体占用的内存就是内部属性内存对齐后的大小
- 内存回收快,用栈帧控制入栈出栈即可,没有处理堆内存的开销
- 不需要引用计数(结构体中使用引用类型作为属性除外)
- 一般是静态派发,运行速度快,也方便编译器优化,如内联等
- 赋值时深拷贝。系统通过 Copy-On_Write,避免不必要的 copy,减少拷贝开销
- 没有隐式数据分享,具有独立性不可变性
- 可通过协议和泛型实现抽象。但实现协议的结构体内存大小不同,因此无法直接放入数组中,为了存储的一致性,传参赋值时系统会引入中间层 Existential Container。此处如果结构体属性较多会复杂一点,但苹果也会有优化,减少开销。总体来说,值类型的多态是有成本的,系统会尽量优化。开发者要考虑的是:减少动态多态把协议直接当做类来使用,需要更多考虑静态多态,多结合泛型约束来使用。
引用类型
- 引用类型在内存使用上没有值类型高效,在堆上创建并需要有栈指针指向该区域,增加了堆内存分配和回收的开销
- 赋值消耗小,一般是浅拷贝复制指针。但有引用计数成本
- 多个指针可指向同一内存,独立性差,容易误操作
- 非线程安全,要考虑原子性,多线程需要线程锁配合
- 需要引用计数来控制内存释放,使用不当会有野指针、内存泄漏和循环引用的风险
- 允许继承,但继承的Side effect就是子类与父类的紧耦合。比如系统的 UIStackView 主要目的只是用来布局使用,但却不得不继承 UIView 的所有属性和方法。
Swift 提供了更强大的值类型试图来解决 OC 的 OOP 的子类与父类的紧耦合、对象隐式数据共享、非线程安全、引用计数等典型痛点。Swift 标准库主要有值类型组成,基本数据类型如 Int、Double、Float、String、Array、Dictionary、Set、Tuple 也都是结构体。当然,虽然值类型有众多优点,但也不是说要完全抛弃 Class,具体情况具体分析。
网友评论