Skip to content

Rust 所有权

所有权是 Rust 最独特的特性之一,它让 Rust 在不需要垃圾回收的情况下保证内存安全。本章节将介绍 Rust 的所有权系统。

所有权规则

Rust 的所有权系统有以下三条规则:

  1. 每个值都有一个所有者:每个值在 Rust 中都有且只有一个所有者变量。
  2. 所有者离开作用域时,值会被丢弃:当所有者变量离开作用域时,它所拥有的值会被自动释放。
  3. 一个值只能有一个所有者:当值被赋给另一个变量时,所有权会转移。

所有权转移

基本类型的所有权

对于基本类型(如整数、布尔值等),赋值时会进行复制,而不是所有权转移:

rust
fn main() {
    let x = 5;
    let y = x; // 复制 x 的值
    
    println!("x = {}, y = {}", x, y); // 可以同时使用 x 和 y
}

复杂类型的所有权

对于复杂类型(如字符串、向量等),赋值时会发生所有权转移:

rust
fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // 所有权从 s1 转移到 s2
    
    // println!("s1 = {}", s1); // 错误:s1 不再拥有值
    println!("s2 = {}", s2); // 正确:s2 现在拥有值
}

函数调用时的所有权

当函数接收参数时,所有权会转移:

rust
fn take_ownership(s: String) {
    println!("Got string: {}", s);
    // s 离开作用域,值被释放
}

fn main() {
    let s = String::from("hello");
    take_ownership(s);
    // println!("s = {}", s); // 错误:s 不再拥有值
}

返回值的所有权

函数可以通过返回值转移所有权:

rust
fn give_ownership() -> String {
    let s = String::from("hello");
    s // 返回 s,所有权转移给调用者
}

fn main() {
    let s = give_ownership();
    println!("Got string: {}", s);
}

借用

为了避免所有权转移带来的不便,Rust 提供了借用机制:

不可变借用

rust
fn print_string(s: &String) {
    println!("String: {}", s);
    // s 是借用的,不会获取所有权
}

fn main() {
    let s = String::from("hello");
    print_string(&s); // 传递引用
    println!("s = {}", s); // 仍然可以使用 s
}

可变借用

rust
fn modify_string(s: &mut String) {
    s.push_str(", world");
}

fn main() {
    let mut s = String::from("hello");
    modify_string(&mut s); // 传递可变引用
    println!("s = {}", s); // s 被修改了
}

借用规则

  1. 同一时间只能有一个可变借用或多个不可变借用:不能同时有可变借用和不可变借用。
  2. 借用必须在所有者的作用域内:借用的生命周期不能超过所有者的生命周期。
rust
fn main() {
    let mut s = String::from("hello");
    
    let r1 = &s; // 不可变借用
    let r2 = &s; // 另一个不可变借用,允许
    // let r3 = &mut s; // 错误:不能同时有不可变借用和可变借用
    
    println!("r1 = {}, r2 = {}", r1, r2);
    // r1 和 r2 离开作用域
    
    let r3 = &mut s; // 现在可以可变借用
    println!("r3 = {}", r3);
}

生命周期

生命周期是 Rust 中用于确保引用有效性的机制。生命周期注解使用撇号 ' 表示:

rust
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let s1 = String::from("hello");
    let s2 = "world";
    
    let result = longest(&s1, s2);
    println!("Longest: {}", result);
}

总结

  • 所有权规则:每个值有一个所有者,所有者离开作用域时值被丢弃,一个值只能有一个所有者
  • 所有权转移:复杂类型赋值时会发生所有权转移
  • 借用:通过引用借用值,避免所有权转移
  • 借用规则:同一时间只能有一个可变借用或多个不可变借用
  • 生命周期:确保引用的有效性

所有权系统是 Rust 内存安全的核心,它让 Rust 在不需要垃圾回收的情况下保证内存安全。通过本章节的学习,你应该已经理解了 Rust 的所有权系统的基本概念和使用方法。