Copy-on-Write(Cow)
问题
Cow 是什么?什么时候用它?
答案
Cow 基础
Cow<'a, B> = Clone-on-Write,在需要修改时才进行克隆:
use std::borrow::Cow;
fn process(input: &str) -> Cow<str> {
if input.contains("bad") {
// 需要修改 → 克隆为 String
Cow::Owned(input.replace("bad", "good"))
} else {
// 不需要修改 → 零拷贝返回引用
Cow::Borrowed(input)
}
}
let a = process("hello"); // Cow::Borrowed → 零拷贝
let b = process("bad word"); // Cow::Owned → 分配了新 String
典型使用场景
1. 避免不必要的字符串克隆
fn normalize(s: &str) -> Cow<str> {
if s.chars().all(|c| c.is_lowercase()) {
Cow::Borrowed(s) // 已经是小写,零拷贝
} else {
Cow::Owned(s.to_lowercase()) // 需要转换
}
}
2. 函数同时接受拥有和借用的值
fn log_message(msg: Cow<str>) {
println!("[LOG] {}", msg);
}
log_message(Cow::Borrowed("静态消息"));
log_message(Cow::Owned(format!("动态消息 {}", 42)));
常见面试问题
Q1: Cow<str> 和 String 有什么区别?
答案:
String 总是拥有堆分配的数据。Cow<str> 可能是借用(零开销)也可能是拥有。当大多数情况不需要修改时,Cow 避免了不必要的克隆。
Q2: Cow 的修改操作如何工作?
答案:
let mut cow = Cow::Borrowed("hello");
// to_mut() 如果是 Borrowed 会先克隆
cow.to_mut().push_str(" world");
// 现在 cow 一定是 Owned
to_mut() 保证返回一个可变引用——如果当前是 Borrowed 状态,先触发克隆。