Rust 第一天:所有权到底在解决什么
学一门新技术,先在脑子里建立「问题地图」——它存在是为了解决什么?比「怎么写」重要。
第一天:撞上 ownership
之前写 JS/Python,从来没想过「这块内存是谁的」。
Rust 第一天就撞墙:编译器不让我编译,因为「这块内存的所有权不对」。
先想清楚:所有权在解决什么
C/C++ 的内存问题,本质只有一个:
谁负责释放内存?
| 方案 | 代表 | 代价 |
|---|---|---|
| 手动管理 | C / malloc/free | 忘了 free → 内存泄漏;free 早了 → use-after-free |
| 垃圾回收 | Java / Python / JS | 运行时开销;STW 暂停 |
Rust 选了第三条路:
编译时定死「谁拥有这块内存」,出作用域自动释放。
不是 GC,不是手动——是编译器帮你管。
第一天的认知卡点
卡点 1:「移动」到底在干什么?
let s1 = String::from("hello");
let s2 = s1; // s1 被移动了
// println!("{}", s1); // 编译错误!
我第一反应是:「为什么不能复制?」
后来想清楚:复制是有代价的(堆内存拷贝)。Rust 默认不复制,强制你「想清楚要不要复制」——要复制就显式写 .clone()。
认知:Rust 不是在「限制你」,是在「逼你 upfront 想清楚代价」。
卡点 2:借用为什么要有生命周期?
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() { x } else { y }
}
// 编译错误:返回值生命周期不明确
第一反应是:「编译器怎么这么笨,x 和 y 都是传进来的,返回哪个不就行了吗?」
后来想清楚:返回的引用,到底指向谁的內存? 如果 x 出作用域了,返回的引用就悬空了。
认知:生命周期标注不是在「告诉编译器怎么跑」,是在「逼你把依赖关系写清楚」。
第一天结束时的认知地图
还没想清楚的
- 「生命周期」和「泛型」放在一起时(lifetime bounds),为什么需要写
'a: 'b这种语法?它在约束什么? - Rc/Arc 为什么是「引用计数」而不是「所有权转移」?什么场景下需要它们?
- Rust 的「所有权」和 JS 的「闭包捕获」有没有本质联系?(都是「这段内存归谁」的问题)
(这些问题不急着答案——先让它们在脑子里转几天。)
这篇笔记的「道」
学一门新技术,不要急着「跑起来」。 先花一天,把「它存在是为了解决什么」想清楚。 剩下的,查文档就行。