深入理解所有权系统
发布时间:2025年1月6日
所有权的概念
所有权是 Rust 最独特的特性,它保证了内存安全而无需垃圾回收器。
所有权规则
Rust 的所有权系统有三个基本规则:
- 每个值都有一个所有者
- 一次只能有一个所有者
- 当所有者离开作用域,值将被丢弃
实践示例
所有权转移示例
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 的所有权移动到 s2
// println!("{}", s1); // 错误:s1 已经失效
println!("{}", s2); // 正确:s2 现在拥有该值
}
所有权转移流程
graph TD
A[变量1 创建] --> B[堆上分配内存]
B --> C[变量1 获得所有权]
C --> D[移动所有权给变量2]
D --> E[变量1 失效]
D --> F[变量2 获得所有权]
F --> G[变量2 离开作用域]
G --> H[内存释放]
引用与借用
通过引用,我们可以在不获取所有权的情况下使用值:
引用和借用示例
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("'{}' 的长度是 {}", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
可变引用
可变引用示例
fn main() {
let mut s = String::from("hello");
change(&mut s);
println!("{}", s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
切片类型
字符串切片示例
fn main() {
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];
println!("{} {}", hello, world);
// 也可以这样写
let slice = &s[..]; // 获取整个字符串的切片
}
生命周期
生命周期是引用保持有效的作用域:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
练习
尝试完成以下练习来加深理解:
- 创建一个函数,接受一个字符串的所有权并返回该字符串的反转版本
- 实现一个函数,使用引用来修改字符串的内容
- 编写一个使用生命周期标注的函数