这个练习介绍 Cow:Clone-On-Write(写时复制)。
Cow 可以暂时借用数据,只有在确实需要修改时,才把借用的数据克隆成自有数据。
需要填写的答案
三个 todo!() 分别是:
// reference_no_mutation
Borrowed
// owned_no_mutation
Owned
// owned_mutation
Owned
因此测试部分应为:
Cow<[i32]> 的两种状态
主要有两种形式:
Borrowed
Owned
也就是说,它既可以保存借用的切片,也可以保存自己拥有的 Vec<i32>。
abs_all 的工作方式
这段代码把所有负数转换成正数。
关键是:
input.to_mut
to_mut() 会返回一个可变引用:
- 如果当前是
Cow::Owned,直接返回内部Vec - 如果当前是
Cow::Borrowed,先克隆借用的数据,再转成Cow::Owned - 如果没有调用
to_mut(),就不会发生克隆
四个测试的状态变化
1. 借用数据,并且需要修改
let vec = vec!;
let mut input = from;
abs_all;
初始状态:
Borrowed
发现 -1,需要修改。由于原始 vec 只是借用的,不能直接修改,因此 to_mut() 会执行克隆:
Borrowed -> Owned
所以结果是:
Owned
原始 vec 不会被改变。
2. 借用数据,但不需要修改
let vec = vec!;
let mut input = from;
abs_all;
所有元素都已经是非负数,因此这段代码永远不会执行:
input.to_mut = -value;
所以不会发生克隆,状态保持:
Borrowed -> Borrowed
结果是:
Borrowed
3. 一开始就拥有数据,且不需要修改
let vec = vec!;
let mut input = from;
这里没有使用 &,所以 Vec 的所有权直接移动进 Cow:
Owned
即使后续没有修改,也不会变成 Borrowed,因为它从一开始就是拥有数据的:
Owned -> Owned
4. 一开始就拥有数据,且需要修改
let vec = vec!;
let mut input = from;
初始状态已经是:
Owned
调用 to_mut() 时,直接取得内部 Vec 的可变引用,不需要再次克隆:
Owned -> Owned
结果仍然是:
Owned
matches! 的含义
例如:
assert!;
表示检查 input 是否匹配:
Borrowed
其中 _ 表示忽略内部具体内容。
类似地:
assert!;
表示检查它是否拥有内部的 Vec<i32>。
这个练习的核心规律是:
| 初始数据 | 是否需要修改 | 最终状态 |
|---|---|---|
| 借用数据 | 是 | Cow::Owned |
| 借用数据 | 否 | Cow::Borrowed |
| 自有数据 | 是 | Cow::Owned |
| 自有数据 | 否 | Cow::Owned |
Cow 的优势就是:只在必要时复制数据,避免不必要的克隆。