Skip to content

Rust 引用与借用

引用与借用是 Rust 所有权系统的重要组成部分,它们允许我们在不获取所有权的情况下使用值。本章节将介绍 Rust 中的引用与借用。

引用

引用是一种特殊的指针,它指向某个值的内存地址,但不拥有该值的所有权:

rust
fn main() {
    let s1 = String::from("hello");
    let s2 = &s1; // s2 是 s1 的引用
    
    println!("s1: {}", s1);
    println!("s2: {}", s2);
}

不可变引用

默认情况下,引用是不可变的,不能通过引用修改值:

rust
fn main() {
    let s1 = String::from("hello");
    let s2 = &s1; // 不可变引用
    
    // s2.push_str(", world"); // 错误:不能通过不可变引用修改值
    println!("s2: {}", s2);
}

可变引用

使用 &mut 可以创建可变引用,通过可变引用可以修改值:

rust
fn main() {
    let mut s1 = String::from("hello");
    let s2 = &mut s1; // 可变引用
    
    s2.push_str(", world");
    println!("s2: {}", s2);
    println!("s1: {}", s1); // s1 也被修改了
}

借用规则

Rust 有严格的借用规则,确保内存安全:

  1. 同一时间只能有一个可变引用或多个不可变引用:不能同时有可变引用和不可变引用。
  2. 借用必须在所有者的作用域内:借用的生命周期不能超过所有者的生命周期。
  3. 可变引用不能被别名:同一时间只能有一个可变引用指向同一个值。

规则 1:同一时间只能有一个可变引用或多个不可变引用

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);
}

规则 3:可变引用不能被别名

rust
fn main() {
    let mut s = String::from("hello");
    
    let r1 = &mut s; // 可变引用
    // let r2 = &mut s; // 错误:同一时间只能有一个可变引用
    
    println!("r1 = {}", r1);
}

函数中的借用

传递不可变引用

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 被修改了
}

引用的生命周期

引用的生命周期是指引用有效的时间段。在 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);
}

总结

  • 引用:指向某个值的内存地址,但不拥有该值的所有权
  • 不可变引用&T,不能修改值
  • 可变引用&mut T,可以修改值
  • 借用规则
    1. 同一时间只能有一个可变引用或多个不可变引用
    2. 借用必须在所有者的作用域内
    3. 可变引用不能被别名
  • 生命周期:引用有效的时间段

引用与借用是 Rust 所有权系统的核心概念,它们允许我们在不获取所有权的情况下使用值,同时保证内存安全。通过本章节的学习,你应该已经掌握了 Rust 中的引用与借用。