Rust 所有权系统

Rust 的所有权系统(Ownership System)是该语言最独特、最重要的特性,也是其实现内存安全(Memory Safety)而不需要垃圾回收器(Garbage Collector, GC)或手动内存管理的基石
理解所有权系统是掌握 Rust 的关键。它围绕着三个核心规则展开:
核心规则 1:所有权(Ownership)
Rust 中的每个值都有一个对应的所有者(owner)
当值被赋值给一个新的变量、作为函数参数传递或从函数返回时,该值的所有权会发生转移。
fn main() {
    let s1 = String::from("hello"); // s1 现在是 "hello" 的所有者

    let s2 = s1; // 所有权从 s1 转移(Move)到了 s2

    // println!("{}, world!", s1); // 错误!s1 不再拥有数据,已经失效了
    println!("{}, world!", s2); // s2 是新的所有者,可以使用
}
  • Move 语义: 默认情况下,Rust 使用“移动”(Move)语义。当所有权转移后,旧的所有者将无法再使用该值。
  • Copy 语义: 实现了 Copy Trait 的类型(例如整数 i32、布尔值 bool、字符 char、定长数组、以及只包含这些类型的元组)在赋值时会进行数据复制,而不是所有权转移。
核心规则 2:借用(Borrowing)
借用是一种在不转移所有权的情况下使用值的方式。你可以通过创建引用(References)来“借用”数据。
引用使用 & 符号创建。
fn main() {
    let s1 = String::from("hello");

    // 创建一个不可变引用 s2,借用 s1 的数据
    // s1 仍然是所有者
    let s2 = &s1; 

    println!("{}, world!", s1); // s1 仍然有效
    println!("{}, world!", s2); // s2 也可以使用
    // s2 离开作用域,借用结束
    // s1 离开作用域,释放内存
}
核心规则 3:借用规则(The Borrowing Rules)
为了确保安全,Rust 编译器强制执行严格的借用规则:
在一个特定的时间点,你只能拥有以下情况之一:
  • 一个可变引用 (&mut T):同时只能存在一个可变引用。
  • 任意数量的不可变引用 (&T):可以有多个读取者同时存在。
你不能同时拥有一个可变引用和任何其他引用(无论是可变还是不可变)。
这个规则防止了“数据竞争”(Data Races)
fn main() {
    let mut s = String::from("hello");

    let r1 = &s; // 第一个不可变引用
    let r2 = &s; // 第二个不可变引用
    println!("r1: {}, r2: {}", r1, r2); // 可以同时使用这两个引用

    // ❌ 错误!不能在不可变引用 r1 和 r2 存在的同时创建可变引用 r3
    // let r3 = &mut s; 
    // println!("r3: {}", r3); 
    
    // ✅ 正确:当 r1 和 r2 的作用域结束后,可以创建 r3
    {
      let r3 = &mut s;
      r3.push_str(", world");
      println!("r3: {}", r3);
    }
    
    // 再次使用 s 是安全的
    println!("s: {}", s);
}

4.关于for循环遍历对象所有权的问题

对比表
 
语法等价写法所有权影响item 的类型循环后 msg 是否可用
for x in msg msg.into_iter() 转移 (Move) T (值)
for x in &msg msg.iter() 借用 (Ref) &T (不可变引用)
for x in msg.iter() msg.iter() 借用 (Ref) &T (不可变引用)
for x in &mut msg msg.iter_mut() 可变借用 &mut T (可变引用)
  • 通常写 for item in &msg 而不是 for item in msg.iter()。这两者在效果上是完全等价的,但前者更符合 Rust 社区的简洁审美。
  • 关于隐式调用:
    for 循环会自动调用 IntoIterator::into_iter
    • 对 msg(值)调用返回 T
    • 对 &msg(引用)调用返回 &T
    • 对 &mut msg(可变引用)调用返回 &mut T

5. 编程惯例建议

总结:所有权系统的优势
Rust 的所有权系统和借用规则共同实现了零成本抽象:
  • 内存安全: 编译器在编译时静态检查所有规则,消除了空指针、双重释放、野指针等常见的内存错误。
  • 没有运行时开销: 没有垃圾回收器监控内存,没有引用计数检查开销。
  • 性能保证: 开发者可以像在 C/C++ 中一样精确控制内存,同时享有现代语言的安全保障。

思考题:

1.Rust 的所有权系统和借用规则共同实现了零成本抽象是否与RefCell相矛盾呢?

 

posted @ 2025-11-28 17:28  PKICA  阅读(24)  评论(0)    收藏  举报