1. 值类型(Value Types)
-
定义:每个实例持有独立的数据副本,赋值或传参时发生深拷贝。
- 典型类型:
Struct、Enum、基础类型(Int、String、Array等)。
- 典型类型:
-
实现原理:
- 栈内存分配:默认在栈上分配(高效,无需GC)。
-
写时复制(Copy-on-Write):Swift 对大型值类型(如
Array)优化,仅在修改时复制数据。
-
优点:
- 线程安全:数据独立,无需锁。
- 无副作用:函数内修改不影响外部变量。
- 确定性析构:离开作用域立即释放。
-
缺点:
- 大对象复制开销:频繁操作大型结构体可能影响性能。
2. 引用类型(Reference Types)
-
定义:实例共享同一内存地址,赋值或传参时传递指针。
- 典型类型:
Class、Closure。
- 典型类型:
-
实现原理:
- 堆内存分配:实例存储在堆,通过引用计数(ARC)管理生命周期。
- 指针传递:变量存储的是内存地址。
-
优点:
- 高效共享:适合需要多对象共享同一状态的场景。
- 继承与多态:支持面向对象特性。
-
缺点:
- 线程安全隐患:共享状态需同步机制。
-
循环引用风险:需用
weak或unowned打破强引用。
3. 如何选择合适的类型?
-
选值类型当:
- 需要不可变性(如配置参数)。
- 数据独立性优先(如坐标点
CGPoint)。 - 避免副作用(函数式编程)。
-
选引用类型当:
- 需要共享状态(如全局管理器
UserDefaults.standard)。 - 需要继承或Objective-C互操作。
- 实例生命周期需精确控制(如UI组件)。
- 需要共享状态(如全局管理器
4. 面试常见问题
-
值类型和引用类型在内存管理上有何区别?
- 值类型栈分配,引用类型堆分配+ARC。
-
写时复制(CoW)是如何实现的?
- 示例:
Array在修改时检查引用计数,若>1则复制底层存储。
- 示例:
-
为什么Swift的String、Array采用结构体而非类?
- 不可变性与性能优化,避免不必要的共享。
-
如何避免引用类型的循环引用?
- 使用
weak或unowned修饰闭包或委托。
- 使用
-
以下代码输出什么?为什么?
struct S { var value: Int } class C { var value: Int = 0 } var a = S(value: 1) var b = a b.value = 2 print(a.value) // 1 let x = C() let y = x y.value = 2 print(x.value) // 2
5. 高级场景
- 值类型+协议:通过协议实现轻量级多态(无需继承)。
-
混合使用:
class内部封装struct数据(如ViewModel持有Model结构体)。
总结
-
默认优先选值类型:Swift标准库大量使用结构体(如
Int、Array),因其安全、高效。 - 必要时用引用类型:当共享状态或需要继承时选择类。