Rust 所有权、借用与生命周期实战入门
Rust 所有权、借用与生命周期实战入门
Rust 最特别的地方不是语法,而是它把内存管理规则前移到了编译期。刚开始写 Rust 时,很多人会觉得编译器很严格,但真正理解所有权之后,会发现它是在帮你提前挡住很多运行时问题。
一、所有权是什么
Rust 中每个值都有一个所有者,同一时间只能有一个所有者。当所有者离开作用域,值就会被自动释放。
1 | fn main() { |
name 离开 main 作用域后,对应的堆内存会被释放,不需要手动 free,也不需要 GC。
二、移动语义
对于 String 这类拥有堆内存的数据,赋值会发生移动:
1 | let a = String::from("hello"); |
a 的所有权已经移动给 b,所以不能继续使用 a。这避免了两个变量同时释放同一块内存的问题。
三、借用解决传参问题
如果只是读取数据,不必转移所有权,可以使用引用:
1 | fn print_name(name: &String) { |
这叫不可变借用。函数可以读取 name,但不会拿走它。
四、可变借用的限制
可变借用允许修改数据,但同一时间只能存在一个可变引用:
1 | let mut count = 1; |
这个限制看起来麻烦,本质上是在防止数据竞争。尤其在并发环境里,它非常有价值。
五、生命周期什么时候需要写
多数情况下,生命周期可以由编译器自动推断。只有当函数返回引用,并且编译器无法判断引用来自哪里时,才需要显式标注:
1 | fn longest<'a>(left: &'a str, right: &'a str) -> &'a str { |
'a 表示返回值的生命周期不会超过两个参数中较短的那个。
六、学习建议
不要一开始就死磕复杂生命周期。先掌握三个判断:
- 数据是谁创建的
- 函数是否需要拥有它
- 是读取、修改,还是返回引用
当你能回答这三个问题,Rust 的所有权模型就会从“编译器刁难我”变成“编译器替我守门”。