swift的value type和reference type
讓value type 效能更好的 copy on write
也許有人會想到,value type 每次都要複製,效能應該會比較不好。不過其實不用太擔心,Swift 很聰明,針對某些 value type 它應用 copy on write 的技巧讓效能更好。 像 String型別即運用了 copy on write 的技巧,因此它不會馬上複製,它只在內容修改時才進行複製。以剛剛我們用 struct 定義 Baby,for 迴圈生 3000 個寶寶的例子,以下程式碼並不會讓記憶體成長到七十幾 MB,因為 Baby 的屬性 heyJude 是字串型別,一開始 3000 個寶寶的 heyJude 的內容和 cuteBaby 的heyJude 一樣,所以 3000 個 newBaby的heyJude 可以先讀取 cuteBaby 的heyJude,還不用複製產生新的 heyJude 字串。
understanding-swift-copy-on-write-mechanisms
Value and Reference Types (Apple’s Blog)
So the array2 data is being copied only when we mutate it as you can see in the console print.
代码验证
var array1: [Int] = [0, 1, 2, 3]
var array2 = array1
printZ(address: array1)
printZ(address: array2)
//Let's mutate array2 to see what's
array2.append(4)
printZ(address: array2)
func printZ(address o: UnsafeRawPointer ) {
print(String(format: "%p", Int(bitPattern: o)))
}
打印
0x600001768160
0x600001768160
0x600002626240
浅析Swift中的Copy-on-Write
value types
已深度思考(用时 24 秒)
好的,用户现在询问关于Swift中的“value types”(值类型)。我需要详细解释这个概念,同时结合之前的对话历史。用户之前对Swift术语卡感兴趣,已经举过一些例子,现在特别问到值类型。首先,我得确保自己完全理解值类型在Swift中的定义、特点以及使用场景。
用户之前提到过提升Swift编程能力和英语水平,所以在回答时要结合中英文术语,可能还要提供代码示例和实际应用场景。用户可能希望了解值类型与引用类型的区别,以及为什么在Swift中值类型如此重要,比如结构体和枚举是值类型,而类是引用类型。
考虑到用户之前对术语卡的兴趣,我应该按照之前的四要素结构来组织内容:术语、定义、代码示例、情景句。此外,用户可能需要了解值类型的优缺点,以及何时使用值类型而不是引用类型。可能还需要提到Swift标准库中的值类型,比如数组、字符串、字典等,这些都是结构体实现的。
另外,用户之前提到过在阅读英文文档时遇到困难,所以解释时要尽量清晰,可能用中英对照的方式,同时提供实际代码示例帮助理解。还要注意用户可能存在的常见误区,比如认为值类型总是被复制,实际上Swift在优化时会进行写时复制(copy-on-write),所以性能上并不会差。
可能需要提到内存管理方面的内容,比如值类型存储在栈上,而引用类型在堆上,值类型更安全,因为每个实例都有独立的内存,不会出现意外的共享状态。这也是Swift鼓励使用值类型的原因之一,尤其是在多线程环境中避免数据竞争。
最后,要确保回答结构清晰,分点说明,并给出实际应用建议,比如在需要封装简单数据时使用结构体,需要继承或多态时使用类。同时,结合用户之前的学习方法,比如制作术语卡,可以建议用户如何将值类型的内容整理到自己的知识库中。
以下是关于 Swift 中 Value Types(值类型) 的详细术语卡,结合定义、核心特性、代码示例和应用场景,帮助你深入理解这一关键概念:
术语卡:Value Types(值类型)
1. 定义(Definition)
值类型是一种当被赋值给变量/常量或传递给函数时,会创建独立副本的数据类型。
其核心特征是:每个实例拥有独立的内存空间,修改副本不影响原始值。
2. 核心特性
| 特性 | 说明 |
|---|---|
| 复制行为 | 赋值或传参时生成完整拷贝(但 Swift 优化为写时复制Copy-on-Write) |
| 内存位置 | 通常存储在栈(Stack)上,分配/释放更快 |
| 线程安全 | 天然线程安全(无共享状态) |
| Swift 典型代表 | Struct(结构体)、Enum(枚举)、基本类型(Int, String 等) |
3. 代码示例(Code Examples)
基础示例
// 定义结构体(值类型)
struct Point {
var x: Int
var y: Int
}
var pointA = Point(x: 1, y: 2)
var pointB = pointA // 创建副本
pointB.x = 3 // 修改副本不影响原值
print(pointA.x) // 1
print(pointB.x) // 3
对比引用类型(Reference Type)
// 定义类(引用类型)
class Person {
var name: String
init(name: String) { self.name = name }
}
let personA = Person(name: "Alice")
let personB = personA // 共享同一实例
personB.name = "Bob"
print(personA.name) // "Bob"(原值被修改)
print(personB.name) // "Bob"
4. 应用场景(Use Cases)
优先使用值类型的情况
| 场景 | 理由 | 示例 |
|---|---|---|
| 封装简单数据模型 | 避免不必要的共享状态 | struct User { var id: Int; var name: String } |
| 需要线程安全 | 多线程环境下无需加锁 | 网络请求的配置参数(struct RequestConfig) |
| 函数式编程 | 支持不可变性(Immutable) | 使用 let 声明值类型变量保证数据不变 |
| 高性能需求 | 栈分配更快,且写时复制优化减少内存开销 | Swift 标准库的 Array, String, Dictionary 均为结构体实现 |
5. 进阶知识(Advanced Concepts)
写时复制(Copy-on-Write)
- 机制:Swift 值类型(如
Array)在赋值时不立即复制内存,直到某个副本被修改时才会真正复制 - 自定义实现:
struct MyArray<T> { private var storage: [T] = [] var count: Int { storage.count } mutating func append(_ element: T) { if !isKnownUniquelyReferenced(&storage) { storage = storage.copy() // 检测到共享时复制 } storage.append(element) } }
值类型与协议(Protocol)
可通过协议扩展增强功能,同时保持值语义:
protocol Drawable {
func draw()
}
struct Circle: Drawable {
func draw() { print("Drawing circle") }
}
let shapes: [Drawable] = [Circle(), Circle()]
shapes.forEach { $0.draw() }
6. 情景句(Context Sentences)
-
开发实践:
"When designing a model for API response data, prefer usingstructoverclassto avoid accidental shared state mutations."
(设计 API 响应数据模型时,优先使用结构体而非类,避免意外的共享状态修改) -
性能优化:
"Swift’sArrayuses copy-on-write to optimize performance of value types, making them efficient even with large data sets."
(Swift 数组通过写时复制优化值类型性能,即使处理大数据集也很高效) -
线程安全:
"By passing a struct across threads, we eliminate the risk of data races since each thread gets its own copy."
(通过跨线程传递结构体,每个线程获得独立副本,从而消除数据竞争风险)
7. 常见误区(Misconceptions)
| 误区 | 真相 |
|---|---|
| “值类型总是立即深拷贝” | Swift 通过写时复制优化,只在必要时拷贝 |
| “值类型不能有方法” | 结构体和枚举可以定义方法(如 mutating func) |
| “值类型性能一定优于引用类型” | 小对象更高效,但频繁拷贝大对象可能影响性能(需合理设计) |
8. 练习建议(Practice)
- 重构代码:将某个
class改为struct,观察行为变化 - 性能测试:使用
measure方法对比值类型/引用类型的创建速度func testPerformance() { measure { var points = [Point]() for _ in 0..<10_000 { points.append(Point(x: 1, y: 2)) } } } - 探索标准库:查看
Array或String的 Swift 源码(GitHub链接),理解其值类型实现
通过理解值类型,你可以写出更安全、高效的 Swift 代码。现在尝试用 struct 重构你的下一个数据模型吧! 🛠️