总结一下 Rust 的所有权规则
所有权规则(Ownership Rules)
1. 每个值都有一个所有者(Each value has one owner)
let s1 = String::from("hello"); // s1 是 "hello" 的所有者
let s2 = s1; // 所有权从 s1 移动到 s2
// println!("{}", s1); // 错误!s1 已经不再有效
2. 同一时刻只能有一个所有者(Only one owner at a time)
let s1 = String::from("hello");
let s2 = s1; // s1 的所有权移动到 s2
// s1 在这里已经无效了
3. 当所有者离开作用域时,值会被丢弃(Value is dropped when owner goes out of scope)
{
let s = String::from("hello"); // s 进入作用域
// 使用 s
} // s 离开作用域,内存被自动释放
移动语义(Move Semantics)
基本类型(实现了 Copy trait)
let x = 5;
let y = x; // x 被复制给 y,x 仍然有效
println!("{}", x); // 正常工作
复杂类型(未实现 Copy trait)
let s1 = String::from("hello");
let s2 = s1; // s1 的所有权移动到 s2
// println!("{}", s1); // 编译错误!
借用规则(Borrowing Rules)
1. 不可变借用规则
let mut s = String::from("hello");
let r1 = &s; // 不可变借用
let r2 = &s; // 另一个不可变借用
// let r3 = &mut s; // 错误!不能同时有可变和不可变借用
2. 可变借用规则
let mut s = String::from("hello");
let r1 = &mut s; // 可变借用
// let r2 = &mut s; // 错误!不能同时有多个可变借用
// let r3 = &s; // 错误!不能同时有可变和不可变借用
3. 借用必须始终有效
fn main() {
let r; // 声明引用
{
let x = 5; // x 进入作用域
r = &x; // r 引用 x
} // x 离开作用域,r 变成了悬垂引用
// println!("{}", r); // 错误!
}
智能指针解决方案
Rc - 引用计数
use std::rc::Rc;
let data = Rc::new(String::from("hello"));
let data_clone1 = Rc::clone(&data); // 引用计数 +1
let data_clone2 = Rc::clone(&data); // 引用计数 +1
// 当所有 Rc 都离开作用域时,数据被释放
RefCell - 运行时借用检查
use std::cell::RefCell;
let data = RefCell::new(5);
*data.borrow_mut() += 10; // 可变借用
println!("{}", *data.borrow()); // 不可变借用
Rc<RefCell> - 组合使用
use std::rc::Rc;
use std::cell::RefCell;
let data = Rc::new(RefCell::new(5));
let data_clone = Rc::clone(&data);
*data_clone.borrow_mut() += 10; // 修改共享数据
println!("{}", *data.borrow()); // 看到修改后的值
生命周期(Lifetimes)
基本语法
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
生命周期省略规则
// 编译器自动推断生命周期
fn first_word(s: &str) -> &str { ... } // 等同于 fn first_word<'a>(s: &'a str) -> &'a str
实际应用示例
你的 CubeSat 项目中的使用
let base = Rc::new(RefCell::new(GroundStation { radio_freq: 87.65 }));
// Rc 允许多个所有者
// RefCell 允许运行时借用检查
// 结合使用可以安全地共享可变状态
let sat = base.borrow().connect(id); // 不可变借用
base.borrow_mut().radio_freq += 1.0; // 可变借用
总结
Rust 的所有权系统通过以下方式保证内存安全:
- 编译时检查 - 防止悬垂引用和数据竞争
- 零成本抽象 - 运行时没有垃圾收集器开销
- 明确的所有权语义 - 代码意图清晰,易于理解
- 智能指针 - 在需要时提供额外的灵活性
浙公网安备 33010602011771号