所有权(Ownership)是 Rust 最独特、最核心的特性,它让 Rust 无需垃圾回收器即可保证内存安全。理解所有权是掌握 Rust 的关键。
1. 所有权规则
Rust 的所有权系统基于三条核心规则:
规则一:Rust 中的每一个值都有一个变量作为它的所有者(owner)。
规则二:在同一时刻,值有且只有一个所有者。
规则三:当所有者离开作用域(scope)时,该值将被丢弃(drop)。
1 | fn main() { |
作用域与 Drop
1 | fn main() { |
2. 栈与堆
理解栈(Stack)和堆(Heap)对于理解所有权至关重要。
2.1 概念说明
1 | 栈(Stack) 堆(Heap) |
2.2 栈上数据 vs 堆上数据
1 | fn main() { |
3. 移动语义(Move)
3.1 基本类型的 Copy
基本类型(标量类型)实现了 Copy trait,赋值时会自动复制值。
1 | fn main() { |
3.2 String 等堆上数据的移动
1 | fn main() { |
3.3 函数参数的所有权转移
1 | fn main() { |
3.4 函数返回值的所有权转移
1 | fn main() { |
4. Copy trait 与 Clone trait
4.1 Copy trait
Copy trait 使类型在赋值时自动进行按位复制(浅复制),原变量仍然有效。
1 | fn main() { |
4.2 Clone trait
Clone 提供显式的深复制能力。
1 | fn main() { |
4.3 Copy 与 Clone 的关系
1 | // Copy 是 Clone 的子 trait |
5. 引用与借用
引用(Reference)允许你使用值而不获取其所有权,这称为”借用”(Borrowing)。
5.1 不可变引用(&T)
1 | fn main() { |
5.2 可变引用(&mut T)
1 | fn main() { |
5.3 引用规则
1 | fn main() { |
5.4 悬垂引用(Dangling Reference)
Rust 在编译期防止悬垂引用的出现。
1 | fn main() { |
6. 切片(Slice)
切片是对集合中一段连续元素的引用,没有所有权。
6.1 字符串切片(&str)
1 | fn main() { |
6.2 切片与所有权的安全性
1 | fn main() { |
6.3 注意 UTF-8 字符串切片
1 | fn main() { |
6.4 数组切片(&[T])
1 | fn main() { |
7. 所有权与函数
7.1 所有权转移模式总结
1 | fn main() { |
7.2 选择传参方式的指导原则
1 | fn main() { |
8. 所有权与结构体
8.1 结构体拥有自己字段的所有权
1 |
|
8.2 结构体中使用引用(需要生命周期标注)
1 | // 结构体中使用引用需要生命周期标注 |
8.3 结构体方法中的所有权
1 |
|
9. 常见所有权问题与解决方案
9.1 问题:在循环中使用移动过的值
1 | fn main() { |
9.2 问题:从集合中取出元素
1 | fn main() { |
9.3 问题:结构体部分字段移动
1 |
|
9.4 问题:闭包捕获变量的所有权
1 | fn main() { |
10. 所有权的内存模型图解
10.1 栈上数据(Copy 语义)
1 | let x: i32 = 42; |
1 | fn main() { |
10.2 堆上数据(Move 语义)
1 | let s1 = String::from("hello"); |
1 | fn main() { |
10.3 Clone(深复制)
1 | let s1 = String::from("hello"); |
1 | fn main() { |
10.4 引用(借用)
1 | let s = String::from("hello"); |
1 | fn main() { |
10.5 切片
1 | let s = String::from("hello world"); |
1 | fn main() { |
总结
所有权是 Rust 的核心特性,通过以下机制保证内存安全:
- 三大规则:每个值有一个所有者,同时只能有一个所有者,所有者离开作用域时值被丢弃
- 移动语义:堆上数据赋值时转移所有权,防止双重释放
- Copy/Clone:基本类型自动 Copy,复杂类型显式 Clone
- 借用规则:任意多个不可变引用 或 恰好一个可变引用,防止数据竞争
- 悬垂引用:编译器阻止引用指向已释放的数据
- 切片:对数据的部分引用,无所有权,安全地访问集合的一部分
掌握这些概念后,你将能够编写既安全又高效的 Rust 代码。下一章我们将学习控制流程。