深入理解所有权系统

发布时间:2025年1月6日

所有权的概念

所有权是 Rust 最独特的特性,它保证了内存安全而无需垃圾回收器。

所有权规则

Rust 的所有权系统有三个基本规则:

  • 每个值都有一个所有者
  • 一次只能有一个所有者
  • 当所有者离开作用域,值将被丢弃

实践示例

所有权转移示例
fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // s1 的所有权移动到 s2
    
    // println!("{}", s1); // 错误:s1 已经失效
    println!("{}", s2); // 正确:s2 现在拥有该值
}

所有权转移流程

graph TD A[变量1 创建] --> B[堆上分配内存] B --> C[变量1 获得所有权] C --> D[移动所有权给变量2] D --> E[变量1 失效] D --> F[变量2 获得所有权] F --> G[变量2 离开作用域] G --> H[内存释放]

引用与借用

通过引用,我们可以在不获取所有权的情况下使用值:

引用和借用示例
fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);
    println!("'{}' 的长度是 {}", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

可变引用

可变引用示例
fn main() {
    let mut s = String::from("hello");
    change(&mut s);
    println!("{}", s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

切片类型

字符串切片示例
fn main() {
    let s = String::from("hello world");
    let hello = &s[0..5];
    let world = &s[6..11];
    println!("{} {}", hello, world);
    
    // 也可以这样写
    let slice = &s[..];  // 获取整个字符串的切片
}

生命周期

生命周期是引用保持有效的作用域:

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

练习

尝试完成以下练习来加深理解:

  1. 创建一个函数,接受一个字符串的所有权并返回该字符串的反转版本
  2. 实现一个函数,使用引用来修改字符串的内容
  3. 编写一个使用生命周期标注的函数
返回首页