核心心智模型
Rust 的三条铁律:
- 每个值只有一个所有者。
- 同一时间,要么有多个不可变借用,要么只有一个可变借用。
- 借用的生命周期不能超过被借用的值。
把它翻译成人话就是:你可以共享,但不能乱改;要改就独占。
一个常见的“借用冲突”
fn main() {
let mut list = vec![1, 2, 3];
let first = &list[0];
list.push(4); // 编译器会阻止这里
println!("{}", first);
}
为什么不让?因为 push 可能触发扩容,导致 first 指向的内存失效。Rust 选择 提前拒绝,把潜在的运行时崩溃变成编译时错误。
让代码“过编译”的姿势
思路很简单:缩短借用的作用域。
fn main() {
let mut list = vec![1, 2, 3];
{
let first = &list[0];
println!("{}", first);
}
list.push(4);
}
或者直接把需要的数据拷贝出来:
let first = list[0];
list.push(4);
生命周期:不是“写出来就安全”,而是“写明白就安全”
fn longest<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() > b.len() { a } else { b }
}
'a 的意义是:返回值一定活得不比参数更久。这不是玄学,是给编译器的安全合同。
一个实用结论
- 逻辑先拆小,再放进函数里,生命周期会更清晰。
- 数据结构越扁平,借用冲突越少。
- 如果被逼到墙角,考虑
clone或Arc<Mutex<...>>,但要知道自己在换安全还是性能。
Rust 的哲学就是:先给你痛,后给你稳。