rust 引用类似java中的对象引用,如果是直接赋值某个变量,就意味着所有权转移
- 引用|借用是指向被引用内存地址
- 所有权转移,原变量失效不可再用
#![allow(unused)] fn main() { let x = String::from("hello"); let y = &x; println!("x的内存地址:{:p}",y); let z = &y; println!("{:p}",*z); println!("{:p}",&z); println!("{:p}",&x); }
所有权规则(Ownership Rules)
1.每个值都有一个所有者(Each value has one owner)
#![allow(unused)] fn main() { let s1 = String::from("hello"); // s1 是 "hello" 的所有者 let s2 = s1; // 所有权从 s1 移动到 s2 // println!("{}", s1); // 错误!s1 已经不再有效 }
2. 同一时刻只能有一个所有者(Only one owner at a time)
#![allow(unused)] fn main() { let s1 = String::from("hello"); let s2 = s1; // s1 的所有权移动到 s2 // s1 在这里已经无效了 }
3. 当所有者离开作用域时,值会被丢弃(Value is dropped when owner goes out of scope)
#![allow(unused)] fn main() { { let s = String::from("hello"); // s 进入作用域 // 使用 s } // s 离开作用域,内存被自动释放 }
移动语义(Move Semantics) 基本类型(实现了 Copy trait)
#![allow(unused)] fn main() { let x = 5; let y = x; // x 被复制给 y,x 仍然有效 println!("{}", x); // 正常工作 }
复杂类型(未实现 Copy trait)
#![allow(unused)] fn main() { let s1 = String::from("hello"); let s2 = s1; // s1 的所有权移动到 s2 // println!("{}", s1); // 编译错误! }
借用规则(Borrowing Rules)
- 不可变借用规则
#![allow(unused)] fn main() { let mut s = String::from("hello"); let r1 = &s; // 不可变借用 let r2 = &s; // 另一个不可变借用 // let r3 = &mut s; // 错误!不能同时有可变和不可变借用 }
- 可变借用规则
#![allow(unused)] fn main() { let mut s = String::from("hello"); let r1 = &mut s; // 可变借用 // let r2 = &mut s; // 错误!不能同时有多个可变借用 // let r3 = &s; // 错误!不能同时有可变和不可变借用 }
- 借用必须始终有效
fn main() { let r; // 声明引用 { let x = 5; // x 进入作用域 r = &x; // r 引用 x } // x 离开作用域,r 变成了悬垂引用 // println!("{}", r); // 错误! }
智能指针解决方案 Rc - 引用计数
#![allow(unused)] fn main() { 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 - 运行时借用检查
#![allow(unused)] fn main() { use std::cell::RefCell; let data = RefCell::new(5); *data.borrow_mut() += 10; // 可变借用 println!("{}", *data.borrow()); // 不可变借用 }
Rc
#![allow(unused)] fn main() { 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)
基本语法
#![allow(unused)] fn main() { fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } }
生命周期省略规则
#![allow(unused)] fn main() { // 编译器自动推断生命周期 fn first_word(s: &str) -> &str { ... } // 等同于 fn first_word<'a>(s: &'a str) -> &'a str }
实际应用示例 你的 CubeSat 项目中的使用
#![allow(unused)] fn main() { 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 的所有权系统通过以下方式保证内存安全:
- 编译时检查 - 防止悬垂引用和数据竞争
- 零成本抽象 - 运行时没有垃圾收集器开销
- 明确的所有权语义 - 代码意图清晰,易于理解
- 智能指针 - 在需要时提供额外的灵活性
以上转自:https://www.cnblogs.com/JohannaFeng/p/19050150