可变方法与写时复制语义
了解为何需要 mutating,以及 Swift 的 COW 优化如何工作。
可变方法与写时复制语义 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。
欢迎
修改存储属性的结构体方法必须标记为 `mutating`。Swift 还使用写时复制(COW)来提高值语义的效率。
mutating 关键字
```swift
struct Counter {
var count = 0
mutating func increment() { count += 1 }
mutating func reset() { count = 0 }
}
var c = Counter()
c.increment() // count = 1
```
如果没有 `mutating`,编译器会拒绝修改 `self` 的方法。
为什么需要 mutating
结构体是值类型。传递结构体时,传递的是一个*副本*。编译器需要 `mutating` 来知道某个方法会修改原始值:
```swift
let c = Counter()
c.increment() // ❌ cannot use mutating on let
```
在 mutating 方法中重新赋值给 self
`mutating` 方法可以完全替换 `self`:
```swift
struct Toggle {
var isOn: Bool
mutating func flip() { self = Toggle(isOn: !isOn) }
}
```
值语义:复制行为
```swift
var a = Counter()
var b = a // b is an independent copy
a.increment()
print(a.count) // 1
print(b.count) // 0 — unaffected
```
为结构体赋值时,会复制其所有存储属性。
写时复制(COW)
Swift 的内置集合类型(数组、字典、集合、字符串)使用 COW:
```swift
var a = [1,2,3]
var b = a // no copy yet — shared storage
b.append(4) // NOW a copy is made — a is unchanged
print(a) // [1,2,3]
print(b) // [1,2,3,4]
```
COW 的重要性
如果没有 COW,每次结构体赋值都会深度复制所有内容。COW 意味着复制的成本很低(只需增加引用计数),直到发生变化时才会触发真正的复制。这使值类型在大多数场景下能达到与引用类型相当的速度。
实现自定义 COW
```swift
struct Buffer {
private var storage: NSMutableData
private mutating func ensureUnique() {
if !isKnownUniquelyReferenced(&storage) {
storage = storage.mutableCopy() as! NSMutableData
}
}
mutating func append(_ byte: UInt8) {
ensureUnique()
// safe to mutate storage now
}
}
```
mutating 与协议
会修改值的协议方法必须在协议中标记为 `mutating`:
```swift
protocol Resettable {
mutating func reset()
}
struct Counter: Resettable {
var count = 0
mutating func reset() { count = 0 }
}
```
实现该协议的类不需要 `mutating`(类是引用类型)。
存储在 let 中的结构体完全不可变
```swift
let pt = Point(x: 1, y: 2)
pt.x = 3 // ❌ even though x is var inside Point
```
结构体存储在 `let` 中时,其中任何存储属性都不能被修改。
快速检查
Swift 的写时复制会在什么时候真正执行复制?
总结
主要要点:
• `mutating` 标记会修改结构体属性的方法
• 不能在 `let` 结构体上调用 `mutating` 方法
• 赋值会复制结构体;COW 让集合的复制成本很低
• COW 只会在第一次修改时触发真正的复制
• 使用 `isKnownUniquelyReferenced` 实现自定义 COW
课程完成!接下来:类继承。
常见问题解答
「可变方法与写时复制语义」课时是免费的吗?
是的 — 「可变方法与写时复制语义」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。
「可变方法与写时复制语义」这节课中我会学到什么?
了解为何需要 mutating,以及 Swift 的 COW 优化如何工作。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Swift Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「可变方法与写时复制语义」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Swift Academy 课中编写并运行代码吗?
能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 成员初始化器与自定义初始化器
- 存储属性与属性观察器
- 结构体中的计算属性
- 可变方法与写时复制语义