Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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)

  1. 不可变借用规则
#![allow(unused)]
fn main() {
let mut s = String::from("hello");
let r1 = &s;    // 不可变借用
let r2 = &s;    // 另一个不可变借用
// let r3 = &mut s; // 错误!不能同时有可变和不可变借用
}
  1. 可变借用规则
#![allow(unused)]
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;    // 可变借用
// let r2 = &mut s; // 错误!不能同时有多个可变借用
// let r3 = &s;     // 错误!不能同时有可变和不可变借用
}
  1. 借用必须始终有效
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