在这里插入图片描述

第5章 所有权系统

5.1 所有权概念详解

5.1.1 所有权的基本规则

Rust的所有权系统是其最独特的特性,也是保证内存安全的核心机制。让我们从基础开始,深入理解这一革命性的概念。

fn ownership_basic_rules() {
println!("=== 所有权基本规则 ===");
// 规则1: 每个值都有一个所有者
let s1 = String::from("hello"); // s1 是这个字符串的所有者
println!("s1 = {}", s1);
// 规则2: 同一时间只能有一个所有者
let s2 = s1; // 所有权从 s1 移动到 s2
// println!("{}", s1); // 编译错误!s1 不再拥有数据
// 规则3: 当所有者离开作用域时,值将被丢弃
{
let temp = String::from("temporary");
println!("临时字符串: {}", temp);
} // temp 离开作用域,内存被释放
// println!("{}", temp); // 编译错误!temp 已不存在
// 演示所有权的转移
demonstrate_ownership_transfer();
}
fn demonstrate_ownership_transfer() {
println!("\n=== 所有权转移演示 ===");
// 移动语义 - 对于堆分配的数据
let heap_string = String::from("堆上的数据");
let moved_string = heap_string; // 所有权转移
// println!("{}", heap_string); // 错误:heap_string 不再有效
// 克隆 - 创建数据的完整副本
let original = String::from("原始数据");
let cloned = original.clone(); // 创建深拷贝
println!("original = {}, cloned = {}", original, cloned); // 两者都有效
// 拷贝语义 - 对于栈上的数据
let x = 5;
let y = x; // 拷贝值,不是移动
println!("x = {}, y = {}", x, y); // 两者都有效
// 函数调用中的所有权转移
let data = String::from("重要数据");
take_ownership(data);
// println!("{}", data); // 错误:所有权已转移到函数中
// 返回值转移所有权
let returned_data = give_ownership();
println!("返回的数据: {}", returned_data);
}
fn take_ownership(s: String) {
println!("在函数中获取所有权: {}", s);
} // s 离开作用域,内存被释放
fn give_ownership() -> String {
let s = String::from("新创建的数据");
s // 所有权转移给调用者
}
fn ownership_and_functions() {
println!("\n=== 函数与所有权 ===");
// 1. 参数传递转移所有权
let s = String::from("hello");
takes_ownership(s); // s 的所有权移动进函数
// s 在这里不再有效
let x = 5;
makes_copy(x); // x 应该移动进函数,但 i32 是 Copy 的,所以后面可继续使用 x
// 2. 返回值转移所有权
let s1 = gives_ownership(); // gives_ownership 将返回值移给 s1
let s2 = String::from("hello"); // s2 进入作用域
let s3 = takes_and_gives_back(s2); // s2 被移动到函数中,返回值移给 s3
println!("s1 = {}, s3 = {}", s1, s3);
// 3. 返回多个值的所有权
let (s4, len) = calculate_length(s1);
println!("'{}' 的长度是 {}", s4, len);
}
fn takes_ownership(some_string: String) {
println!("{}", some_string);
} // some_string 离开作用域,drop 被调用,内存被释放
fn makes_copy(some_integer: i32) {
println!("{}", some_integer);
} // some_integer 离开作用域,没有特别的事情发生
fn gives_ownership() -> String {
let some_string = String::from("hello");
some_string // 返回 some_string 并移出给调用者
}
fn takes_and_gives_back(a_string: String) -> String {
a_string // 返回 a_string 并移出给调用者
}
fn calculate_length(s: String) -> (String, usize) {
let length = s.len();
(s, length) // 返回字符串和其长度
}

5.1.2 栈与堆的内存模型

要深入理解所有权,必须首先理解Rust的栈和堆内存模型。

fn stack_vs_heap_memory() {
println!("=== 栈与堆内存模型 ===");
// 栈内存:固定大小,快速分配和释放
let x = 5;           // i32,存储在栈上
let y = 3.14;        // f64,存储在栈上
let z = true;        // bool,存储在栈上
println!("栈变量: x={}, y={}, z={}", x, y, z);
// 堆内存:动态大小,通过指针访问
let heap_string = String::from("这是一个堆分配的字符串");
let heap_vector = vec![1, 2, 3, 4, 5]; // 向量在堆上分配
println!("堆数据: {}, {:?}", heap_string, heap_vector);
// 内存布局分析
analyze_memory_layout();
// 性能对比
performance_comparison();
}
fn analyze_memory_layout() {
println!("\n=== 内存布局分析 ===");
use std::mem;
// 栈上类型的大小
println!("栈类型大小:");
println!("  i32: {} 字节", mem::size_of::<i32>());
  println!("  f64: {} 字节", mem::size_of::<f64>());
    println!("  bool: {} 字节", mem::size_of::<bool>());
      println!("  引用: {} 字节", mem::size_of::<&String>());
      // 堆分配的类型
      let empty_string = String::new();
      let small_string = String::from("hi");
      let large_string = String::from("这是一个很长的字符串");
      println!("\n字符串内存使用:");
      println!("  空字符串: {} 字节(栈上)", mem::size_of_val(&empty_string));
      println!("  小字符串: {} 字节(栈上)", mem::size_of_val(&small_string));
      println!("  大字符串: {} 字节(栈上)", mem::size_of_val(&large_string));
      // 字符串实际数据在堆上
      println!("  字符串容量: {}, {}, {}",
      empty_string.capacity(),
      small_string.capacity(),
      large_string.capacity());
      // 向量的内存布局
      let empty_vec: Vec<i32> = vec![];
        let small_vec = vec![1, 2, 3];
        let large_vec: Vec<i32> = (0..100).collect();
          println!("\n向量内存使用:");
          println!("  空向量: {} 字节(栈上)", mem::size_of_val(&empty_vec));
          println!("  小向量: {} 字节(栈上)", mem::size_of_val(&small_vec));
          println!("  大向量: {} 字节(栈上)", mem::size_of_val(&large_vec));
          println!("  向量容量: {}, {}, {}",
          empty_vec.capacity(),
          small_vec.capacity(),
          large_vec.capacity());
          }
          fn performance_comparison() {
          println!("\n=== 栈与堆性能对比 ===");
          use std::time::Instant;
          // 栈分配性能测试
          let start = Instant::now();
          for _ in 0..1_000_000 {
          let _x = 42;           // 栈分配
          let _y = 3.14;         // 栈分配
          let _z = [0u8; 64];    // 栈分配(小数组)
          }
          let stack_duration = start.elapsed();
          // 堆分配性能测试
          let start = Instant::now();
          for _ in 0..1_000_000 {
          let _x = String::from("hello");        // 堆分配
          let _y = vec![0u8; 64];               // 堆分配
          let _z = Box::new([0u8; 1024]);       // 堆分配(大数组)
          }
          let heap_duration = start.elapsed();
          println!("栈分配耗时: {:?}", stack_duration);
          println!("堆分配耗时: {:?}", heap_duration);
          println!("堆分配比栈分配慢 {:.1} 倍",
          heap_duration.as_nanos() as f64 / stack_duration.as_nanos() as f64);
          // 所有权转移的性能影响
          ownership_transfer_performance();
          }
          fn ownership_transfer_performance() {
          println!("\n=== 所有权转移性能 ===");
          use std::time::Instant;
          // 测试1: 移动小数据(实际上只是复制指针)
          let small_data = String::from("small");
          let start = Instant::now();
          for _ in 0..1_000_000 {
          let _moved = small_data.clone(); // 使用clone来模拟移动,因为不能重复移动同一个值
          }
          let small_move_duration = start.elapsed();
          // 测试2: 移动大数据
          let large_data = vec![0u8; 10_000];
          let start = Instant::now();
          for _ in 0..1_000_000 {
          let _moved = large_data.clone(); // 使用clone模拟
          }
          let large_move_duration = start.elapsed();
          println!("小数据移动耗时: {:?}", small_move_duration);
          println!("大数据移动耗时: {:?}", large_move_duration);
          println!("移动操作本质是廉价的指针复制");
          }

5.1.3 Copy和Move语义

理解Copy和Move语义是掌握所有权系统的关键。

fn copy_vs_move_semantics() {
println!("=== Copy 与 Move 语义 ===");
// 1. Copy 类型 - 栈上数据
let x = 5;
let y = x; // 拷贝值
println!("Copy语义: x={}, y={}", x, y); // 两者都可用
// 2. Move 类型 - 堆上数据
let s1 = String::from("hello");
let s2 = s1; // 移动所有权
// println!("{}", s1); // 错误!s1 不再有效
println!("Move语义: s2={}", s2);
// 3. 哪些类型实现了 Copy trait
demonstrate_copy_types();
// 4. 哪些类型是 Move 语义
demonstrate_move_types();
// 5. 自定义类型的 Copy 行为
custom_type_copy_behavior();
}
fn demonstrate_copy_types() {
println!("\n=== Copy 类型示例 ===");
// 所有整数类型都是 Copy
let a: i8 = 1;
let b: i16 = 2;
let c: i32 = 3;
let d: i64 = 4;
let e: isize = 5;
// 所有浮点数类型都是 Copy
let f: f32 = 1.0;
let g: f64 = 2.0;
// 布尔类型是 Copy
let h: bool = true;
// 字符类型是 Copy
let i: char = 'a';
// 元组当所有元素都是 Copy 时也是 Copy
let j: (i32, f64) = (1, 2.0);
let k = j; // 拷贝
println!("元组拷贝: j={:?}, k={:?}", j, k);
// 数组当元素是 Copy 时也是 Copy
let l: [i32; 3] = [1, 2, 3];
let m = l; // 拷贝
println!("数组拷贝: l={:?}, m={:?}", l, m);
// 不可变引用是 Copy
let n = &42;
let o = n; // 拷贝引用
println!("引用拷贝: n={}, o={}", n, o);
}
fn demonstrate_move_types() {
println!("\n=== Move 类型示例 ===");
// String 是 Move 类型
let s1 = String::from("hello");
let s2 = s1; // 移动
// println!("{}", s1); // 错误!
// Vec 是 Move 类型
let v1 = vec![1, 2, 3];
let v2 = v1; // 移动
// println!("{:?}", v1); // 错误!
// Box 是 Move 类型
let b1 = Box::new(5);
let b2 = b1; // 移动
// println!("{}", b1); // 错误!
// 包含 Move 类型的元组也是 Move 类型
let t1 = (String::from("hello"), 42);
let t2 = t1; // 移动
// println!("{:?}", t1); // 错误!
// 自定义结构体默认是 Move 类型
  #[derive(Debug)]
struct Person {
name: String,
age: u32,
}
let p1 = Person { name: String::from("Alice"), age: 30 };
let p2 = p1; // 移动
// println!("{:?}", p1); // 错误!
}
fn custom_type_copy_behavior() {
println!("\n=== 自定义类型的 Copy 行为 ===");
// 1. 默认情况下,自定义类型是 Move 语义
  #[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
let p1 = Point { x: 1, y: 2 };
let p2 = p1; // 移动(但实际只是栈上复制,因为没有堆数据)
// println!("{:?}", p1); // 错误!虽然都是栈数据,但默认是Move
// 2. 显式实现 Copy trait
  #[derive(Debug, Clone, Copy)]
struct CopyPoint {
x: i32,
y: i32,
}
let cp1 = CopyPoint { x: 1, y: 2 };
let cp2 = cp1; // 拷贝
println!("Copy类型: cp1={:?}, cp2={:?}", cp1, cp2); // 两者都可用
// 3. 实现 Copy 的条件
println!("\n实现Copy的条件:");
println!("  - 类型的所有组件都实现了Copy");
println!("  - 类型不包含任何Drop实现");
println!("  - 类型本身是POD(普通旧数据)");
// 4. 不能实现 Copy 的情况
  #[derive(Debug)]
struct NonCopyPoint {
x: i32,
name: String, // String 不是 Copy,所以整个结构体也不能是 Copy
}
let ncp1 = NonCopyPoint { x: 1, name: String::from("test") };
let ncp2 = ncp1; // 移动
// println!("{:?}", ncp1); // 错误!
// 5. 检查类型是否实现了 Copy
check_copy_trait();
}
fn check_copy_trait() {
println!("\n=== 检查 Copy trait 实现 ===");
// 使用编译时检查
fn is_copy<T: Copy>() -> bool {
  true
  }
  // 这些类型实现了 Copy
  assert!(is_copy::<i32>());
    assert!(is_copy::<f64>());
      assert!(is_copy::<bool>());
        assert!(is_copy::<char>());
          // 这些类型没有实现 Copy
          // assert!(is_copy::<String>()); // 编译错误
            // assert!(is_copy::<Vec<i32>>()); // 编译错误
              println!("基本类型检查完成");
              }

5.1.4 所有权与函数调用

理解函数调用中所有权的转移是编写正确Rust代码的关键。

fn ownership_and_function_calls() {
println!("=== 所有权与函数调用 ===");
// 1. 参数传递的所有权转移
let s = String::from("hello");
takes_ownership_detailed(s); // s 的所有权移动到函数中
// println!("{}", s); // 错误!s 不再有效
// 2. 返回值的所有权转移
let s1 = gives_ownership_detailed();
let s2 = String::from("world");
let s3 = takes_and_gives_back_detailed(s2); // s2 被移动
println!("s1 = {}, s3 = {}", s1, s3);
// 3. 避免所有权转移的模式
avoid_ownership_transfer();
// 4. 链式函数调用中的所有权
chained_function_calls();
}
fn takes_ownership_detailed(some_string: String) {
println!("函数获取所有权: {}", some_string);
} // some_string 离开作用域,drop 被调用
fn gives_ownership_detailed() -> String {
let some_string = String::from("hello");
some_string // 所有权转移给调用者
}
fn takes_and_gives_back_detailed(a_string: String) -> String {
a_string // 所有权转移给调用者
}
fn avoid_ownership_transfer() {
println!("\n=== 避免所有权转移的模式 ===");
// 模式1: 使用引用(后面会详细讲解)
let s = String::from("hello");
calculate_length_without_take(&s);
println!("仍然拥有字符串: {}", s); // s 仍然有效
// 模式2: 返回元组包含原始数据
let s = String::from("hello");
let (s, len) = calculate_length_and_return(s);
println!("'{}' 的长度是 {}", s, len); // s 仍然有效
// 模式3: 使用克隆
let s1 = String::from("hello");
let len = calculate_length_with_clone(s1.clone());
println!("'{}' 的长度是 {}", s1, len); // s1 仍然有效
// 模式4: 使用 Copy 类型
let x = 5;
use_integer(x);
println!("整数仍然可用: {}", x); // x 仍然可用
}
fn calculate_length_without_take(s: &String) -> usize {
s.len()
}
fn calculate_length_and_return(s: String) -> (String, usize) {
let length = s.len();
(s, length)
}
fn calculate_length_with_clone(s: String) -> usize {
s.len()
} // s 被丢弃,但原始数据不受影响,因为传入的是克隆
fn use_integer(x: i32) {
println!("使用整数: {}", x);
}
fn chained_function_calls() {
println!("\n=== 链式函数调用中的所有权 ===");
// 1. 基本的链式调用
let result = String::from("hello")
.clone() // 创建副本以避免移动原始数据
.to_uppercase() // 返回新的String
.replace("E", "3"); // 返回新的String
println!("链式调用结果: {}", result);
// 2. 构建器模式中的所有权
let user = UserBuilder::new()
.name("Alice".to_string())
.age(30)
.email("alice@example.com".to_string())
.build();
println!("构建的用户: {:?}", user);
// 3. 错误处理链中的所有权
let parse_result = "42"
.parse::<i32>()
  .map(|n| n * 2)
  .map(|n| n.to_string());
  match parse_result {
  Ok(s) => println!("解析结果: {}", s),
  Err(e) => println!("解析错误: {}", e),
  }
  }
    #[derive(Debug)]
  struct User {
  name: String,
  age: u32,
  email: String,
  }
  struct UserBuilder {
  name: Option<String>,
    age: Option<u32>,
      email: Option<String>,
        }
        impl UserBuilder {
        fn new() -> Self {
        UserBuilder {
        name: None,
        age: None,
        email: None,
        }
        }
        fn name(mut self, name: String) -> Self {
        self.name = Some(name);
        self
        }
        fn age(mut self, age: u32) -> Self {
        self.age = Some(age);
        self
        }
        fn email(mut self, email: String) -> Self {
        self.email = Some(email);
        self
        }
        fn build(self) -> User {
        User {
        name: self.name.expect("名称必须设置"),
        age: self.age.expect("年龄必须设置"),
        email: self.email.expect("邮箱必须设置"),
        }
        }
        }

5.2 引用与借用

5.2.1 不可变引用

引用允许你使用值但不获取其所有权,这是Rust中避免所有权转移的主要方式。

fn references_and_borrowing() {
println!("=== 引用与借用 ===");
// 1. 基本引用使用
let s1 = String::from("hello");
let len = calculate_length_with_ref(&s1);
println!("'{}' 的长度是 {}", s1, len); // s1 仍然有效
// 2. 引用与直接使用的区别
compare_reference_vs_direct();
// 3. 多个不可变引用
multiple_immutable_references();
// 4. 引用的作用域
reference_scope();
}
fn calculate_length_with_ref(s: &String) -> usize {
s.len()
} // s 离开作用域,但由于它是引用,不会丢弃它指向的数据
fn compare_reference_vs_direct() {
println!("\n=== 引用与直接使用的对比 ===");
let s = String::from("hello");
// 使用引用 - 不获取所有权
let len1 = calculate_length_with_ref(&s);
println!("使用引用后字符串仍然可用: {}", s);
// 直接使用 - 获取所有权
// let len2 = calculate_length_direct(s); // 这会移动s的所有权
// println!("{}", s); // 错误!s 不再有效
// 解决方案:使用克隆
let len2 = calculate_length_direct(s.clone());
println!("使用克隆后字符串仍然可用: {}", s);
println!("长度1: {}, 长度2: {}", len1, len2);
}
fn calculate_length_direct(s: String) -> usize {
s.len()
}
fn multiple_immutable_references() {
println!("\n=== 多个不可变引用 ===");
let s = String::from("hello");
// 可以同时有多个不可变引用
let r1 = &s;
let r2 = &s;
let r3 = &s;
println!("r1 = {}, r2 = {}, r3 = {}", r1, r2, r3);
// 引用的引用
let rr1 = &r1;
let rr2 = &r2;
println!("rr1 = {}, rr2 = {}", rr1, rr2);
// 在复杂数据结构中使用引用
use_references_in_data_structures();
}
fn use_references_in_data_structures() {
println!("\n=== 在数据结构中使用引用 ===");
  #[derive(Debug)]
struct Book {
title: String,
author: String,
year: u32,
}
let book = Book {
title: String::from("Rust编程"),
author: String::from("张三"),
year: 2023,
};
// 结构体字段的引用
let title_ref = &book.title;
let author_ref = &book.author;
println!("书名: {}, 作者: {}", title_ref, author_ref);
// 在向量中存储引用
let books = vec![
Book { title: String::from("Book1"), author: String::from("Author1"), year: 2020 },
Book { title: String::from("Book2"), author: String::from("Author2"), year: 2021 },
Book { title: String::from("Book3"), author: String::from("Author3"), year: 2022 },
];
let book_refs: Vec<&Book> = books.iter().collect();
for book_ref in book_refs {
println!("{:?}", book_ref);
}
}
fn reference_scope() {
println!("\n=== 引用的作用域 ===");
let s = String::from("hello");
{
let r1 = &s;
println!("内部作用域引用: {}", r1);
} // r1 离开作用域
let r2 = &s;
println!("外部作用域引用: {}", r2);
// 引用的生命周期不能超过被引用数据的生命周期
// let dangling_ref = dangle(); // 这会编译错误
let valid_ref = no_dangle();
println!("有效的引用: {}", valid_ref);
}
// 这个函数会产生悬垂引用,无法编译
// fn dangle() -> &String {
//     let s = String::from("hello");
//     &s // 错误!返回局部变量的引用
// } // s 离开作用域并被丢弃
fn no_dangle() -> String {
let s = String::from("hello");
s // 直接返回所有权
}

5.2.2 可变引用

可变引用允许修改借用的数据,但受到严格的规则限制。

fn mutable_references() {
println!("=== 可变引用 ===");
// 1. 基本可变引用
let mut s = String::from("hello");
change_string(&mut s);
println!("修改后的字符串: {}", s);
// 2. 可变引用的限制
mutable_reference_restrictions();
// 3. 可变引用的作用域
mutable_reference_scope();
// 4. 数据竞争预防
data_race_prevention();
}
fn change_string(s: &mut String) {
s.push_str(", world!");
}
fn mutable_reference_restrictions() {
println!("\n=== 可变引用的限制 ===");
let mut s = String::from("hello");
// 规则1: 同一时间只能有一个可变引用
let r1 = &mut s;
// let r2 = &mut s; // 错误!不能同时有两个可变引用
println!("第一个可变引用: {}", r1);
// 在第一个引用离开作用域后,可以创建新的可变引用
{
let r2 = &mut s;
r2.push_str(" world");
} // r2 离开作用域
let r3 = &mut s;
r3.push_str("!");
println!("最终字符串: {}", r3);
// 规则2: 不能同时有可变引用和不可变引用
let mut data = String::from("data");
let immutable_ref = &data;
// let mutable_ref = &mut data; // 错误!不能同时存在可变和不可变引用
println!("不可变引用: {}", immutable_ref);
// 在不可变引用离开作用域后,可以创建可变引用
// immutable_ref 不再被使用
let mutable_ref = &mut data;
mutable_ref.push_str(" modified");
println!("修改后的数据: {}", mutable_ref);
}
fn mutable_reference_scope() {
println!("\n=== 可变引用的作用域 ===");
let mut s = String::from("hello");
// 可变引用的作用域从声明开始,到最后一次使用结束
let r1 = &mut s;
r1.push_str(" world"); // r1 在这里最后一次使用
// r1 的作用域在这里结束
let r2 = &mut s; // 现在可以创建新的可变引用
r2.push_str("!");
println!("最终结果: {}", r2);
// 非词法作用域生命周期(NLL)示例
nll_example();
}
fn nll_example() {
println!("\n=== 非词法作用域生命周期(NLL)===");
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2);
// r1 和 r2 的作用域在这里结束
let r3 = &mut s; // 现在可以创建可变引用
r3.push_str(" world");
println!("{}", r3);
}
fn data_race_prevention() {
println!("\n=== 数据竞争预防 ===");
// Rust在编译时防止数据竞争的三种情况:
// 1. 两个或多个指针同时访问同一数据
// 2. 至少有一个指针被用来写入数据
// 3. 没有同步数据访问的机制
let mut data = vec![1, 2, 3];
// 安全的使用模式
{
let reference1 = &data[0];
let reference2 = &data[1];
println!("安全访问: {}, {}", reference1, reference2);
} // 引用离开作用域
// 现在可以安全地修改数据
let mutable_ref = &mut data;
mutable_ref.push(4);
println!("修改后的数据: {:?}", mutable_ref);
// 演示数据竞争的危险(在Rust中会被编译器阻止)
demonstrate_data_race_danger();
}
fn demonstrate_data_race_danger() {
println!("\n=== 数据竞争危险演示 ===");
// 这个代码无法编译,演示了Rust如何防止数据竞争
let mut data = vec![1, 2, 3];
let first = &data[0]; // 不可变借用
// 如果允许下面的代码,可能会导致数据竞争:
// data.push(4); // 这可能会重新分配内存,使first成为悬垂指针
// 但在Rust中,编译器会阻止这种情况
println!("第一个元素: {}", first);
// 只有在first不再使用后,才能修改data
// data.push(4); // 取消注释会导致编译错误
}

5.2.3 高级引用模式

探索一些更复杂的引用使用模式和技巧。

fn advanced_reference_patterns() {
println!("=== 高级引用模式 ===");
// 1. 引用与模式匹配
references_and_pattern_matching();
// 2. 引用在数据结构中的使用
references_in_data_structures();
// 3. 引用与迭代器
references_and_iterators();
// 4. 生命周期省略规则
lifetime_elision_rules();
}
fn references_and_pattern_matching() {
println!("\n=== 引用与模式匹配 ===");
// 1. 匹配引用
let value = 42;
let reference = &value;
match reference {
&val => println!("匹配值: {}", val),
}
// 2. 在模式中解构引用
let point = (10, 20);
let point_ref = &point;
match point_ref {
&(x, y) => println!("点坐标: ({}, {})", x, y),
}
// 3. 匹配可变引用
let mut value = 42;
let mut_ref = &mut value;
match mut_ref {
&mut val => {
// val 是 i32,不是引用
println!("可变引用中的值: {}", val);
}
}
// 4. 引用与if let
let optional_value = Some(42);
if let Some(ref value) = optional_value {
println!("可选值中的引用: {}", value);
}
// 5. 在结构体模式匹配中使用引用
  #[derive(Debug)]
struct Person {
name: String,
age: u32,
}
let person = Person {
name: String::from("Alice"),
age: 30,
};
match &person {
&Person { ref name, age } => {
println!("姓名: {}, 年龄: {}", name, age);
}
}
}
fn references_in_data_structures() {
println!("\n=== 数据结构中的引用 ===");
// 1. 包含引用的结构体
  #[derive(Debug)]
struct BookView<'a> {
  title: &'a str,
  author: &'a str,
  year: u32,
  }
  let book_title = String::from("Rust权威指南");
  let book_author = String::from("Steve Klabnik");
  let book_view = BookView {
  title: &book_title,
  author: &book_author,
  year: 2018,
  };
  println!("图书视图: {:?}", book_view);
  // 2. 枚举中的引用
    #[derive(Debug)]
  enum Message<'a> {
    Text(&'a str),
    Number(&'a i32),
    Pair(&'a str, &'a i32),
    }
    let text = "hello";
    let number = 42;
    let msg1 = Message::Text(&text);
    let msg2 = Message::Number(&number);
    let msg3 = Message::Pair(&text, &number);
    println!("消息1: {:?}", msg1);
    println!("消息2: {:?}", msg2);
    println!("消息3: {:?}", msg3);
    // 3. 向量中的引用
    let numbers = vec![1, 2, 3, 4, 5];
    let number_refs: Vec<&i32> = numbers.iter().collect();
    println!("数字引用: {:?}", number_refs);
    // 4. 切片中的引用模式
    let slice = &[1, 2, 3, 4, 5];
    match slice {
    [first, middle @ .., last] => {
    println!("第一个: {}, 中间: {:?}, 最后一个: {}", first, middle, last);
    }
    }
    }
    fn references_and_iterators() {
    println!("\n=== 引用与迭代器 ===");
    let numbers = vec![1, 2, 3, 4, 5];
    // 1. 迭代不可变引用
    println!("不可变引用迭代:");
    for number in &numbers {
    println!("数字: {}", number);
    }
    // 2. 迭代可变引用
    let mut mutable_numbers = vec![1, 2, 3, 4, 5];
    println!("可变引用迭代:");
    for number in &mut mutable_numbers {
    *number *= 2; // 解引用并修改
    println!("加倍后: {}", number);
    }
    // 3. 迭代器方法中的引用
    let sum: i32 = numbers.iter().sum();
    println!("总和: {}", sum);
    let doubled: Vec<i32> = numbers.iter().map(|&x| x * 2).collect();
      println!("加倍后: {:?}", doubled);
      // 4. 过滤引用
      let evens: Vec<&i32> = numbers.iter().filter(|&&x| x % 2 == 0).collect();
      println!("偶数: {:?}", evens);
      // 5. 引用与消费迭代器
      let first_even = numbers.iter().find(|&&x| x % 2 == 0);
      match first_even {
      Some(&x) => println!("第一个偶数: {}", x),
      None => println!("没有偶数"),
      }
      }
      fn lifetime_elision_rules() {
      println!("\n=== 生命周期省略规则 ===");
      // Rust有三条生命周期省略规则,允许在常见情况下省略显式生命周期注解
      // 规则1: 每个引用参数都有自己的生命周期参数
      fn rule1_example(s: &str) -> &str {
      s
      }
      // 规则2: 如果只有一个输入生命周期参数,它被赋予所有输出生命周期参数
      fn rule2_example(s: &str) -> &str {
      s
      }
      // 规则3: 如果有多个输入生命周期参数,但其中一个是&self或&mut self,那么self的生命周期被赋予所有输出生命周期参数
      struct Example {
      value: String,
      }
      impl Example {
      fn rule3_example(&self, s: &str) -> &str {
      if s.is_empty() {
      &self.value
      } else {
      s
      }
      }
      }
      let example = Example { value: String::from("default") };
      let result1 = example.rule3_example("");
      let result2 = example.rule3_example("hello");
      println!("规则3结果1: {}", result1);
      println!("规则3结果2: {}", result2);
      // 无法应用省略规则的情况
      fn no_elision_example<'a>(s1: &'a str, s2: &'a str) -> &'a str {
        if s1.len() > s2.len() {
        s1
        } else {
        s2
        }
        }
        let s1 = "hello";
        let s2 = "world";
        let result = no_elision_example(s1, s2);
        println!("需要显式生命周期: {}", result);
        }

5.3 切片类型

5.3.1 字符串切片

字符串切片是对String中一部分的引用,是Rust中处理字符串的常用方式。

fn string_slices() {
println!("=== 字符串切片 ===");
// 1. 基本字符串切片
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];
println!("原始字符串: {}", s);
println!("切片1: '{}'", hello);
println!("切片2: '{}'", world);
// 2. 切片语法糖
let s = String::from("hello");
let slice1 = &s[..2];    // 从开始到索引2(不含)
let slice2 = &s[2..];    // 从索引2到结束
let slice3 = &s[..];     // 整个字符串
println!("切片语法糖: '{}', '{}', '{}'", slice1, slice2, slice3);
// 3. 字符串字面量就是切片
let literal = "hello world"; // &str 类型
println!("字符串字面量: {}", literal);
// 4. 字符串切片作为函数参数
fn first_word(s: &str) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
let text = String::from("hello world");
let word = first_word(&text);
println!("第一个单词: {}", word);
// 5. 字符串切片的不可变性
string_slice_immutability();
// 6. 字符串切片与UTF-8
string_slices_and_utf8();
}
fn string_slice_immutability() {
println!("\n=== 字符串切片的不可变性 ===");
let mut s = String::from("hello world");
// 创建不可变切片
let word = &s[0..5];
println!("切片: {}", word);
// 可以修改原始字符串
s.push_str("!"); // 这行可以正常工作
println!("修改后的字符串: {}", s);
// 但不能在存在不可变切片时创建可变引用
// let mutable_slice = &mut s[6..]; // 错误!
// 在切片不再使用后,可以创建可变引用
// word 不再被使用
let mutable_slice = &mut s[6..];
mutable_slice.make_ascii_uppercase();
println!("修改切片后: {}", s);
}
fn string_slices_and_utf8() {
println!("\n=== 字符串切片与UTF-8 ===");
let s = "hello 世界 ";
// 字符迭代
println!("字符:");
for (i, c) in s.chars().enumerate() {
println!("  位置 {}: '{}'", i, c);
}
// 字节迭代
println!("字节:");
for (i, &byte) in s.as_bytes().iter().enumerate() {
println!("  位置 {}: 0x{:02x}", i, byte);
}
// 有效的切片范围
let hello = &s[0..5];
println!("有效的切片: '{}'", hello);
// 无效的切片范围(会在运行时panic)
// let invalid = &s[0..6]; // 这会在6处分割字符
// 安全的切片方法
safe_string_slicing();
}
fn safe_string_slicing() {
println!("\n=== 安全的字符串切片 ===");
let s = "hello 世界 ";
// 使用字符边界进行安全切片
fn safe_slice(s: &str, start: usize, end: usize) -> Option<&str> {
// 找到字符边界
let mut char_indices = s.char_indices();
let start_byte = char_indices.nth(start).map(|(i, _)| i);
let end_byte = char_indices.nth(end - start - 1).map(|(i, _)| i);
match (start_byte, end_byte) {
(Some(start), Some(end)) => Some(&s[start..end]),
(Some(start), None) => Some(&s[start..]),
_ => None,
}
}
if let Some(slice) = safe_slice(s, 0, 5) {
println!("安全切片1: '{}'", slice);
}
if let Some(slice) = safe_slice(s, 6, 8) {
println!("安全切片2: '{}'", slice);
}
// 使用标准库的get方法
if let Some(slice) = s.get(0..5) {
println!("get方法切片: '{}'", slice);
}
// 处理可能失败的切片
match s.get(0..100) {
Some(slice) => println!("长切片: '{}'", slice),
None => println!("切片超出范围"),
}
}

5.3.2 数组切片

数组切片是对数组或向量中一部分的引用,提供了灵活的数据访问方式。

fn array_slices() {
println!("=== 数组切片 ===");
// 1. 基本数组切片
let arr = [1, 2, 3, 4, 5];
let slice = &arr[1..4]; // 索引1到3的元素
println!("原始数组: {:?}", arr);
println!("切片: {:?}", slice);
// 2. 向量切片
let vec = vec![1, 2, 3, 4, 5];
let vec_slice = &vec[2..];
println!("原始向量: {:?}", vec);
println!("向量切片: {:?}", vec_slice);
// 3. 可变数组切片
let mut mut_arr = [1, 2, 3, 4, 5];
let mut_slice = &mut mut_arr[1..4];
// 修改切片元素
for elem in mut_slice.iter_mut() {
*elem *= 2;
}
println!("修改后的数组: {:?}", mut_arr);
// 4. 切片的方法和特性
slice_methods_and_traits();
// 5. 多维切片
multi_dimensional_slices();
}
fn slice_methods_and_traits() {
println!("\n=== 切片的方法和特性 ===");
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let slice = &data[..];
// 基本属性
println!("切片长度: {}", slice.len());
println!("是否为空: {}", slice.is_empty());
println!("第一个元素: {:?}", slice.first());
println!("最后一个元素: {:?}", slice.last());
// 元素访问
if let Some(&element) = slice.get(2) {
println!("索引2的元素: {}", element);
}
// 切片迭代
println!("迭代切片:");
for &element in slice {
print!("{} ", element);
}
println!();
// 切片分割
let (left, right) = slice.split_at(5);
println!("分割: {:?} | {:?}", left, right);
// 切片块
println!("分块:");
for chunk in slice.chunks(3) {
println!("  块: {:?}", chunk);
}
// 切片窗口
println!("滑动窗口:");
for window in slice.windows(3) {
println!("  窗口: {:?}", window);
}
// 切片搜索
if let Some(index) = slice.iter().position(|&x| x == 5) {
println!("找到5在位置: {}", index);
}
// 切片排序(需要可变切片)
let mut sortable = [3, 1, 4, 1, 5, 9, 2, 6];
let sort_slice = &mut sortable[..];
sort_slice.sort();
println!("排序后: {:?}", sort_slice);
}
fn multi_dimensional_slices() {
println!("\n=== 多维切片 ===");
// 1. 二维数组切片
let matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
// 获取行切片
let row_slice = &matrix[1..];
println!("行切片: {:?}", row_slice);
// 获取特定行的切片
let second_row = &matrix[1];
println!("第二行: {:?}", second_row);
// 2. 向量的向量切片
let vec_of_vecs = vec![
vec![1, 2, 3],
vec![4, 5, 6],
vec![7, 8, 9],
];
let vec_slice = &vec_of_vecs[0..2];
println!("向量切片: {:?}", vec_slice);
// 3. 复杂切片操作
complex_slice_operations();
}
fn complex_slice_operations() {
println!("\n=== 复杂切片操作 ===");
let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 1. 条件分割
let partitioned: Vec<&[i32]> = data
.chunks(3)
.collect();
println!("按大小分割: {:?}", partitioned);
// 2. 重叠窗口
println!("重叠窗口:");
for window in data.windows(3) {
println!("  {:?}", window);
}
// 3. 切片模式匹配
match &data[..] {
[first, second, .., last] => {
println!("模式匹配: 第一个={}, 第二个={}, 最后一个={}", first, second, last);
}
_ => println!("切片太短"),
}
// 4. 切片与迭代器组合
let sum_of_evens: i32 = data
.chunks(2)
.filter_map(|chunk| chunk.first())
.filter(|&&x| x % 2 == 0)
.sum();
println!("每块第一个偶数的和: {}", sum_of_evens);
// 5. 自定义切片算法
custom_slice_algorithms();
}
fn custom_slice_algorithms() {
println!("\n=== 自定义切片算法 ===");
// 1. 滑动窗口最大值
fn sliding_window_max(arr: &[i32], k: usize) -> Vec<i32> {
  if k > arr.len() {
  return Vec::new();
  }
  let mut result = Vec::new();
  for window in arr.windows(k) {
  if let Some(&max) = window.iter().max() {
  result.push(max);
  }
  }
  result
  }
  let data = [1, 3, -1, -3, 5, 3, 6, 7];
  let maxes = sliding_window_max(&data, 3);
  println!("滑动窗口最大值: {:?}", maxes);
  // 2. 切片旋转
  fn rotate_slice<T: Copy>(slice: &mut [T], k: usize) {
    let n = slice.len();
    if n == 0 { return; }
    let k = k % n;
    slice.reverse();
    slice[..k].reverse();
    slice[k..].reverse();
    }
    let mut rotatable = [1, 2, 3, 4, 5];
    rotate_slice(&mut rotatable, 2);
    println!("旋转后: {:?}", rotatable);
    // 3. 切片分区
    fn partition_slice(slice: &mut [i32], pivot: i32) -> usize {
    let mut i = 0;
    for j in 0..slice.len() {
    if slice[j] < pivot {
    slice.swap(i, j);
    i += 1;
    }
    }
    i
    }
    let mut to_partition = [3, 1, 4, 1, 5, 9, 2, 6];
    let pivot_index = partition_slice(&mut to_partition, 5);
    println!("分区后: {:?}, 分割点: {}", to_partition, pivot_index);
    }

5.3.3 切片与所有权系统

理解切片如何与所有权系统交互是编写正确Rust代码的关键。

fn slices_and_ownership() {
println!("=== 切片与所有权系统 ===");
// 1. 切片的所有权语义
slice_ownership_semantics();
// 2. 切片与借用检查器
slices_and_borrow_checker();
// 3. 返回切片
returning_slices();
// 4. 切片与生命周期
slices_and_lifetimes();
}
fn slice_ownership_semantics() {
println!("\n=== 切片的所有权语义 ===");
// 切片本身不拥有数据,它只是数据的视图
let s = String::from("hello world");
let slice = &s[0..5]; // 创建切片
println!("原始字符串: {}", s);
println!("切片: {}", slice);
// 切片不会影响原始数据的所有权
let s2 = s; // 移动所有权
// println!("{}", slice); // 错误!slice 引用已无效
// 数组切片也是类似的
let arr = [1, 2, 3, 4, 5];
let arr_slice = &arr[1..4];
println!("原始数组: {:?}", arr);
println!("数组切片: {:?}", arr_slice);
// 移动数组后,切片也会失效
let moved_arr = arr;
// println!("{:?}", arr_slice); // 错误!
}
fn slices_and_borrow_checker() {
println!("\n=== 切片与借用检查器 ===");
let mut data = vec![1, 2, 3, 4, 5];
// 创建不可变切片
let slice = &data[1..4];
println!("切片: {:?}", slice);
// 在存在不可变切片时,不能修改原始数据
// data.push(6); // 错误!不能同时存在可变和不可变借用
// 在切片不再使用后,可以修改数据
// slice 不再被使用
data.push(6);
println!("修改后的数据: {:?}", data);
// 可变切片与借用检查
let mut_slice = &mut data[2..];
for elem in mut_slice.iter_mut() {
*elem *= 2;
}
println!("通过可变切片修改后: {:?}", data);
}
fn returning_slices() {
println!("\n=== 返回切片 ===");
// 1. 返回字符串切片
fn get_first_word(s: &str) -> &str {
s.split_whitespace().next().unwrap_or("")
}
let text = String::from("hello world");
let word = get_first_word(&text);
println!("第一个单词: {}", word);
// 2. 返回数组切片
fn get_middle_slice(arr: &[i32]) -> &[i32] {
let mid = arr.len() / 2;
let start = mid.saturating_sub(1);
let end = (mid + 1).min(arr.len());
&arr[start..end]
}
let numbers = [1, 2, 3, 4, 5, 6];
let middle = get_middle_slice(&numbers);
println!("中间切片: {:?}", middle);
// 3. 返回结构体中的切片
struct StringWrapper {
data: String,
}
impl StringWrapper {
fn as_slice(&self) -> &str {
&self.data
}
fn get_substring(&self, start: usize, end: usize) -> &str {
&self.data[start..end]
}
}
let wrapper = StringWrapper { data: String::from("hello world") };
let slice1 = wrapper.as_slice();
let slice2 = wrapper.get_substring(0, 5);
println!("完整切片: {}", slice1);
println!("子字符串: {}", slice2);
}
fn slices_and_lifetimes() {
println!("\n=== 切片与生命周期 ===");
// 1. 显式生命周期注解
fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
  if s1.len() > s2.len() {
  s1
  } else {
  s2
  }
  }
  let s1 = String::from("hello");
  let s2 = "world";
  let result = longest(&s1, s2);
  println!("较长的字符串: {}", result);
  // 2. 结构体中的生命周期
  struct StringSlice<'a> {
    data: &'a str,
    }
    impl<'a> StringSlice<'a> {
      fn new(s: &'a str) -> Self {
      StringSlice { data: s }
      }
      fn get_data(&self) -> &'a str {
      self.data
      }
      }
      let original = String::from("hello world");
      let slice_wrapper = StringSlice::new(&original);
      println!("包装的切片: {}", slice_wrapper.get_data());
      // 3. 复杂的生命周期场景
      complex_lifetime_scenarios();
      }
      fn complex_lifetime_scenarios() {
      println!("\n=== 复杂生命周期场景 ===");
      // 1. 多个生命周期参数
      fn multiple_lifetimes<'a, 'b>(s1: &'a str, s2: &'b str) -> &'a str {
        println!("第二个字符串: {}", s2);
        s1
        }
        let s1 = String::from("hello");
        let result;
        {
        let s2 = String::from("world");
        result = multiple_lifetimes(&s1, &s2);
        println!("结果: {}", result);
        }
        // result 仍然有效,因为它只依赖于 s1 的生命周期
        // 2. 生命周期与迭代器
        struct IterWrapper<'a, T> {
          data: &'a [T],
          index: usize,
          }
          impl<'a, T> IterWrapper<'a, T> {
            fn new(data: &'a [T]) -> Self {
            IterWrapper { data, index: 0 }
            }
            }
            impl<'a, T> Iterator for IterWrapper<'a, T> {
              type Item = &'a T;
              fn next(&mut self) -> Option<Self::Item> {
                if self.index < self.data.len() {
                let item = &self.data[self.index];
                self.index += 1;
                Some(item)
                } else {
                None
                }
                }
                }
                let numbers = [1, 2, 3, 4, 5];
                let wrapper = IterWrapper::new(&numbers);
                println!("自定义迭代器:");
                for num in wrapper {
                print!("{} ", num);
                }
                println!();
                // 3. 静态生命周期
                static_lifetime_examples();
                }
                fn static_lifetime_examples() {
                println!("\n=== 静态生命周期 ===");
                // 'static 生命周期表示数据在整个程序运行期间都有效
                let static_string: &'static str = "这是一个静态字符串";
                println!("静态字符串: {}", static_string);
                // 函数返回 'static 生命周期
                fn get_static_str() -> &'static str {
                "hello world"
                }
                let s = get_static_str();
                println!("函数返回的静态字符串: {}", s);
                // 在数据结构中使用 'static
                struct StaticHolder {
                data: &'static str,
                }
                let holder = StaticHolder { data: "静态数据" };
                println!("静态持有者: {}", holder.data);
                // 注意:不是所有字符串字面量都必须是 'static
                // 但在大多数情况下,字符串字面量确实有 'static 生命周期
                }

5.4 所有权规则实战

5.4.1 常见所有权问题与解决方案

通过实际案例学习如何解决常见的所有权问题。

fn common_ownership_problems() {
println!("=== 常见所有权问题与解决方案 ===");
// 问题1: 使用已移动的值
problem_use_after_move();
// 问题2: 多重可变借用
problem_multiple_mutable_borrows();
// 问题3: 悬垂引用
problem_dangling_references();
// 问题4: 迭代器无效化
problem_iterator_invalidation();
// 问题5: 自引用结构体
problem_self_referential_structs();
}
fn problem_use_after_move() {
println!("\n=== 问题1: 使用已移动的值 ===");
// 错误示例
let s1 = String::from("hello");
let s2 = s1; // 所有权转移
// println!("{}", s1); // 编译错误!s1 不再有效
// 解决方案1: 使用克隆
let s1 = String::from("hello");
let s2 = s1.clone(); // 创建副本
println!("解决方案1: s1={}, s2={}", s1, s2);
// 解决方案2: 使用引用
let s1 = String::from("hello");
let s2 = &s1; // 借用
println!("解决方案2: s1={}, s2={}", s1, s2);
// 解决方案3: 实现Copy trait(仅适用于简单类型)
  #[derive(Copy, Clone, Debug)]
struct Point { x: i32, y: i32 }
let p1 = Point { x: 1, y: 2 };
let p2 = p1; // 拷贝,不是移动
println!("解决方案3: p1={:?}, p2={:?}", p1, p2);
}
fn problem_multiple_mutable_borrows() {
println!("\n=== 问题2: 多重可变借用 ===");
let mut data = vec![1, 2, 3];
// 错误示例
// let ref1 = &mut data;
// let ref2 = &mut data; // 编译错误!不能同时有两个可变引用
// 解决方案1: 使用作用域分隔
{
let ref1 = &mut data;
ref1.push(4);
} // ref1 离开作用域
let ref2 = &mut data;
ref2.push(5);
println!("解决方案1: {:?}", data);
// 解决方案2: 分割可变引用
let mut data = vec![1, 2, 3, 4, 5];
let (left, right) = data.split_at_mut(2);
left[0] = 10;
right[0] = 20;
println!("解决方案2: {:?}", data);
// 解决方案3: 内部可变性(后面会详细讲解)
use std::cell::RefCell;
let data = RefCell::new(vec![1, 2, 3]);
{
let mut ref1 = data.borrow_mut();
ref1.push(4);
}
{
let mut ref2 = data.borrow_mut();
ref2.push(5);
}
println!("解决方案3: {:?}", data.borrow());
}
fn problem_dangling_references() {
println!("\n=== 问题3: 悬垂引用 ===");
// 错误示例(无法编译)
// fn dangle() -> &String {
//     let s = String::from("hello");
//     &s // 错误!返回局部变量的引用
// } // s 离开作用域并被丢弃
// 解决方案1: 返回所有权
fn no_dangle() -> String {
let s = String::from("hello");
s // 直接返回所有权
}
let s = no_dangle();
println!("解决方案1: {}", s);
// 解决方案2: 使用静态生命周期
fn static_reference() -> &'static str {
"hello world" // 字符串字面量有 'static 生命周期
}
let s = static_reference();
println!("解决方案2: {}", s);
// 解决方案3: 接受引用参数并返回引用
fn get_slice<'a>(s: &'a str) -> &'a str {
  &s[0..5]
  }
  let original = String::from("hello world");
  let slice = get_slice(&original);
  println!("解决方案3: {}", slice);
  }
  fn problem_iterator_invalidation() {
  println!("\n=== 问题4: 迭代器无效化 ===");
  let mut data = vec![1, 2, 3, 4, 5];
  // 错误示例
  // for item in &data {
  //     if *item == 3 {
  //         data.push(6); // 编译错误!不能同时存在可变和不可变借用
  //     }
  // }
  // 解决方案1: 收集需要修改的索引,然后单独修改
  let mut indices_to_remove = Vec::new();
  for (i, &item) in data.iter().enumerate() {
  if item == 3 {
  indices_to_remove.push(i);
  }
  }
  for &index in indices_to_remove.iter().rev() {
  data.remove(index);
  }
  data.push(6);
  println!("解决方案1: {:?}", data);
  // 解决方案2: 使用retain方法
  let mut data = vec![1, 2, 3, 4, 5];
  data.retain(|&x| x != 3);
  data.push(6);
  println!("解决方案2: {:?}", data);
  // 解决方案3: 使用索引迭代
  let mut data = vec![1, 2, 3, 4, 5];
  let mut i = 0;
  while i < data.len() {
  if data[i] == 3 {
  data.remove(i);
  } else {
  i += 1;
  }
  }
  data.push(6);
  println!("解决方案3: {:?}", data);
  }
  fn problem_self_referential_structs() {
  println!("\n=== 问题5: 自引用结构体 ===");
  // 错误示例(无法安全实现)
  // struct SelfRef {
  //     data: String,
  //     reference: &String, // 错误!需要生命周期注解
  // }
  // 解决方案1: 使用索引代替引用
  struct SelfRefWithIndex {
  data: String,
  reference_index: usize,
  }
  impl SelfRefWithIndex {
  fn new(data: String) -> Self {
  let reference_index = 0;
  SelfRefWithIndex { data, reference_index }
  }
  fn get_reference(&self) -> &str {
  &self.data[self.reference_index..]
  }
  }
  let self_ref = SelfRefWithIndex::new(String::from("hello world"));
  println!("解决方案1: {}", self_ref.get_reference());
  // 解决方案2: 使用Pin(高级特性,用于固定数据位置)
  use std::marker::PhantomPinned;
  use std::pin::Pin;
  struct SelfRefPinned {
  data: String,
  reference: *const String, // 原始指针
  _pin: PhantomPinned,      // 阻止移动
  }
  impl SelfRefPinned {
  fn new(data: String) -> Pin<Box<Self>> {
    let mut boxed = Box::pin(Self {
    data,
    reference: std::ptr::null(),
    _pin: PhantomPinned,
    });
    let reference = &boxed.data as *const String;
    unsafe {
    let mut_ref = Pin::as_mut(&mut boxed);
    Pin::get_unchecked_mut(mut_ref).reference = reference;
    }
    boxed
    }
    fn get_reference(self: Pin<&Self>) -> &str {
    unsafe { &*self.reference }
    }
    }
    let pinned = SelfRefPinned::new(String::from("hello world"));
    println!("解决方案2: {}", pinned.get_reference());
    // 解决方案3: 使用 arena 或引用计数
    use std::rc::Rc;
    struct SharedData {
    data: Rc<String>,
      }
      impl SharedData {
      fn new(data: String) -> Self {
      SharedData { data: Rc::new(data) }
      }
      fn get_reference(&self) -> &str {
      &self.data
      }
      }
      let shared = SharedData::new(String::from("hello world"));
      println!("解决方案3: {}", shared.get_reference());
      }

5.4.2 所有权模式与最佳实践

学习在实际项目中应用所有权的模式和最佳实践。

fn ownership_patterns_and_best_practices() {
println!("=== 所有权模式与最佳实践 ===");
// 模式1: 构建器模式
builder_pattern();
// 模式2:  RAII (Resource Acquisition Is Initialization)
raii_pattern();
// 模式3: 迭代器适配器模式
iterator_adapter_pattern();
// 模式4: 新类型模式
newtype_pattern();
// 模式5: 内部可变性模式
interior_mutability_pattern();
}
fn builder_pattern() {
println!("\n=== 构建器模式 ===");
  #[derive(Debug)]
struct ConnectionConfig {
host: String,
port: u16,
timeout: u32,
retries: u32,
}
struct ConnectionConfigBuilder {
host: Option<String>,
  port: Option<u16>,
    timeout: Option<u32>,
      retries: Option<u32>,
        }
        impl ConnectionConfigBuilder {
        fn new() -> Self {
        ConnectionConfigBuilder {
        host: None,
        port: None,
        timeout: None,
        retries: None,
        }
        }
        fn host(mut self, host: String) -> Self {
        self.host = Some(host);
        self
        }
        fn port(mut self, port: u16) -> Self {
        self.port = Some(port);
        self
        }
        fn timeout(mut self, timeout: u32) -> Self {
        self.timeout = Some(timeout);
        self
        }
        fn retries(mut self, retries: u32) -> Self {
        self.retries = Some(retries);
        self
        }
        fn build(self) -> Result<ConnectionConfig, String> {
          Ok(ConnectionConfig {
          host: self.host.ok_or("主机名必须设置")?,
          port: self.port.ok_or("端口必须设置")?,
          timeout: self.timeout.unwrap_or(30),
          retries: self.retries.unwrap_or(3),
          })
          }
          }
          let config = ConnectionConfigBuilder::new()
          .host("localhost".to_string())
          .port(8080)
          .timeout(60)
          .build()
          .unwrap();
          println!("构建的配置: {:?}", config);
          }
          fn raii_pattern() {
          println!("\n=== RAII 模式 ===");
          // RAII: 资源获取即初始化
          // 在Rust中,Drop trait 自动提供RAII
          struct File {
          filename: String,
          }
          impl File {
          fn new(filename: &str) -> Result<Self, String> {
            println!("打开文件: {}", filename);
            Ok(File { filename: filename.to_string() })
            }
            }
            impl Drop for File {
            fn drop(&mut self) {
            println!("关闭文件: {}", self.filename);
            }
            }
            struct Transaction<'a> {
              name: &'a str,
              committed: bool,
              }
              impl<'a> Transaction<'a> {
                fn new(name: &'a str) -> Self {
                println!("开始事务: {}", name);
                Transaction { name, committed: false }
                }
                fn commit(mut self) {
                println!("提交事务: {}", self.name);
                self.committed = true;
                // self 在这里被丢弃,但因为我们移动了self,不会调用drop
                }
                }
                impl<'a> Drop for Transaction<'a> {
                  fn drop(&mut self) {
                  if !self.committed {
                  println!("回滚事务: {}", self.name);
                  }
                  }
                  }
                  // 正常提交的事务
                  {
                  let transaction = Transaction::new("正常事务");
                  transaction.commit(); // 提交,不会回滚
                  }
                  // 未提交的事务(会自动回滚)
                  {
                  let _transaction = Transaction::new("未提交事务");
                  // 事务在离开作用域时自动回滚
                  }
                  // 文件RAII示例
                  {
                  let _file = File::new("test.txt").unwrap();
                  // 文件在离开作用域时自动关闭
                  }
                  }
                  fn iterator_adapter_pattern() {
                  println!("\n=== 迭代器适配器模式 ===");
                  let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
                  // 使用迭代器适配器处理数据
                  let result: Vec<String> = numbers
                    .into_iter()                    // 获取所有权迭代器
                    .filter(|&x| x % 2 == 0)       // 过滤偶数
                    .map(|x| x * 3)                // 乘以3
                    .filter(|&x| x > 10)           // 过滤大于10的数
                    .map(|x| x.to_string())        // 转换为字符串
                    .collect();                    // 收集结果
                    println!("迭代器适配器结果: {:?}", result);
                    // 自定义迭代器适配器
                    struct TakeWhileInclusive<I, P> {
                      iter: I,
                      predicate: P,
                      done: bool,
                      }
                      impl<I, P> TakeWhileInclusive<I, P> {
                        fn new(iter: I, predicate: P) -> Self {
                        TakeWhileInclusive { iter, predicate, done: false }
                        }
                        }
                        impl<I: Iterator, P> Iterator for TakeWhileInclusive<I, P>
                          where
                          P: FnMut(&I::Item) -> bool,
                          {
                          type Item = I::Item;
                          fn next(&mut self) -> Option<Self::Item> {
                            if self.done {
                            return None;
                            }
                            let item = self.iter.next()?;
                            if !(self.predicate)(&item) {
                            self.done = true;
                            }
                            Some(item)
                            }
                            }
                            trait TakeWhileInclusiveExt: Iterator + Sized {
                            fn take_while_inclusive<P>(self, predicate: P) -> TakeWhileInclusive<Self, P>
                              where
                              P: FnMut(&Self::Item) -> bool,
                              {
                              TakeWhileInclusive::new(self, predicate)
                              }
                              }
                              impl<I: Iterator> TakeWhileInclusiveExt for I {}
                                let numbers = vec![1, 2, 3, 4, 5, 1, 2, 3];
                                let result: Vec<i32> = numbers
                                  .into_iter()
                                  .take_while_inclusive(|&x| x < 4)
                                  .collect();
                                  println!("自定义适配器结果: {:?}", result);
                                  }
                                  fn newtype_pattern() {
                                  println!("\n=== 新类型模式 ===");
                                  // 新类型模式:用结构体包装现有类型以提供额外的类型安全
                                  // 用户ID和产品ID本质都是u32,但应该是不同的类型
                                  struct UserId(u32);
                                  struct ProductId(u32);
                                  impl UserId {
                                  fn new(id: u32) -> Self {
                                  UserId(id)
                                  }
                                  fn value(&self) -> u32 {
                                  self.0
                                  }
                                  }
                                  impl ProductId {
                                  fn new(id: u32) -> Self {
                                  ProductId(id)
                                  }
                                  fn value(&self) -> u32 {
                                  self.0
                                  }
                                  }
                                  fn get_user_name(user_id: UserId) -> String {
                                  format!("用户{}", user_id.value())
                                  }
                                  fn get_product_name(product_id: ProductId) -> String {
                                  format!("产品{}", product_id.value())
                                  }
                                  let user_id = UserId::new(123);
                                  let product_id = ProductId::new(456);
                                  println!("用户名: {}", get_user_name(user_id));
                                  println!("产品名: {}", get_product_name(product_id));
                                  // 下面的代码会导致编译错误,提供了类型安全
                                  // get_user_name(product_id); // 错误!期望UserId,得到ProductId
                                  // 另一个新类型示例:电子邮件地址
                                  struct Email(String);
                                  impl Email {
                                  fn new(email: &str) -> Result<Self, String> {
                                    if email.contains('@') {
                                    Ok(Email(email.to_string()))
                                    } else {
                                    Err("无效的电子邮件地址".to_string())
                                    }
                                    }
                                    fn value(&self) -> &str {
                                    &self.0
                                    }
                                    }
                                    let email = Email::new("user@example.com").unwrap();
                                    println!("电子邮件: {}", email.value());
                                    }
                                    fn interior_mutability_pattern() {
                                    println!("\n=== 内部可变性模式 ===");
                                    // 内部可变性:允许在不可变引用的情况下修改数据
                                    use std::cell::{RefCell, Cell};
                                    use std::rc::Rc;
                                    // 1. RefCell 示例
                                    let counter = RefCell::new(0);
                                    {
                                    let mut count_ref = counter.borrow_mut();
                                    *count_ref += 1;
                                    } // count_ref 离开作用域,借用结束
                                    {
                                    let count_ref = counter.borrow();
                                    println!("计数器值: {}", *count_ref);
                                    }
                                    // 2. Cell 示例(用于Copy类型)
                                    let cell = Cell::new(42);
                                    cell.set(100); // 不需要可变引用!
                                    println!("Cell值: {}", cell.get());
                                    // 3. 在结构体中使用内部可变性
                                    struct Cache {
                                    data: RefCell<Vec<String>>,
                                      hit_count: Cell<u32>,
                                        miss_count: Cell<u32>,
                                          }
                                          impl Cache {
                                          fn new() -> Self {
                                          Cache {
                                          data: RefCell::new(Vec::new()),
                                          hit_count: Cell::new(0),
                                          miss_count: Cell::new(0),
                                          }
                                          }
                                          fn get(&self, index: usize) -> Option<String> {
                                            let data = self.data.borrow();
                                            if index < data.len() {
                                            self.hit_count.set(self.hit_count.get() + 1);
                                            Some(data[index].clone())
                                            } else {
                                            self.miss_count.set(self.miss_count.get() + 1);
                                            None
                                            }
                                            }
                                            fn add(&self, item: String) {
                                            let mut data = self.data.borrow_mut();
                                            data.push(item);
                                            }
                                            fn stats(&self) -> (u32, u32) {
                                            (self.hit_count.get(), self.miss_count.get())
                                            }
                                            }
                                            let cache = Cache::new();
                                            cache.add("item1".to_string());
                                            cache.add("item2".to_string());
                                            println!("获取item1: {:?}", cache.get(0));
                                            println!("获取不存在的item: {:?}", cache.get(5));
                                            println!("缓存统计: {:?}", cache.stats());
                                            // 4. Rc + RefCell 用于共享所有权和内部可变性
                                            let shared_data = Rc::new(RefCell::new(Vec::new()));
                                            let shared1 = Rc::clone(&shared_data);
                                            let shared2 = Rc::clone(&shared_data);
                                            shared1.borrow_mut().push(1);
                                            shared2.borrow_mut().push(2);
                                            println!("共享数据: {:?}", shared_data.borrow());
                                            }

5.4.3 性能优化与所有权

了解如何利用所有权系统进行性能优化。

fn performance_optimization_with_ownership() {
println!("=== 性能优化与所有权 ===");
// 1. 避免不必要的克隆
avoid_unnecessary_clones();
// 2. 使用移动语义优化
optimize_with_move_semantics();
// 3. 零成本抽象
zero_cost_abstractions();
// 4. 内存布局优化
memory_layout_optimization();
}
fn avoid_unnecessary_clones() {
println!("\n=== 避免不必要的克隆 ===");
// 反模式:不必要的克隆
fn process_string_bad(s: String) -> String {
let result = s.clone(); // 不必要的克隆!
result.to_uppercase()
}
// 好的模式:使用引用
fn process_string_good(s: &str) -> String {
s.to_uppercase()
}
let original = String::from("hello");
let result1 = process_string_bad(original.clone());
let result2 = process_string_good(&original);
println!("结果1: {}", result1);
println!("结果2: {}", result2);
println!("原始字符串: {}", original);
// 在需要所有权时的优化
fn process_string_owned(mut s: String) -> String {
// 直接修改传入的字符串,避免分配新内存
s.make_ascii_uppercase();
s
}
let original = String::from("hello");
let result = process_string_owned(original);
println!("直接修改结果: {}", result);
}
fn optimize_with_move_semantics() {
println!("\n=== 使用移动语义优化 ===");
use std::time::Instant;
// 大型数据结构的移动性能
let large_data: Vec<u8> = (0..10_000_000).map(|x| (x % 256) as u8).collect();
  let start = Instant::now();
  let moved_data = large_data; // 移动,不是拷贝
  let move_duration = start.elapsed();
  println!("移动10MB数据耗时: {:?}", move_duration);
  // 比较移动和克隆的性能
  let large_data: Vec<u8> = (0..1_000_000).map(|x| (x % 256) as u8).collect();
    let start = Instant::now();
    let moved_data = large_data; // 移动
    let move_duration = start.elapsed();
    let large_data_clone: Vec<u8> = (0..1_000_000).map(|x| (x % 256) as u8).collect();
      let start = Instant::now();
      let cloned_data = large_data_clone.clone(); // 克隆
      let clone_duration = start.elapsed();
      println!("移动1MB数据耗时: {:?}", move_duration);
      println!("克隆1MB数据耗时: {:?}", clone_duration);
      println!("移动比克隆快 {:.1} 倍",
      clone_duration.as_nanos() as f64 / move_duration.as_nanos() as f64);
      // 使用移动语义优化函数返回值
      move_semantics_in_functions();
      }
      fn move_semantics_in_functions() {
      println!("\n=== 函数中的移动语义优化 ===");
      // 返回大型数据结构时,移动语义可以避免拷贝
      fn create_large_vector() -> Vec<i32> {
        (0..1_000_000).collect()
        }
        let start = std::time::Instant::now();
        let data = create_large_vector();
        let duration = start.elapsed();
        println!("创建并返回100万元素向量耗时: {:?}", duration);
        // 链式方法调用中的移动优化
        let result = (0..1000)
        .collect::<Vec<i32>>()        // 分配向量
          .into_iter()                  // 转换为所有权迭代器
          .filter(|&x| x % 2 == 0)     // 过滤
          .map(|x| x * 2)              // 映射
          .collect::<Vec<i32>>();      // 重新收集
            println!("链式操作结果长度: {}", result.len());
            }
            fn zero_cost_abstractions() {
            println!("\n=== 零成本抽象 ===");
            // Rust的所有权系统在编译时检查,运行时零成本
            // 1. 迭代器是零成本抽象的典型例子
            let numbers = vec![1, 2, 3, 4, 5];
            // 高级迭代器代码
            let sum: i32 = numbers
            .iter()
            .filter(|&&x| x % 2 == 0)
            .map(|&x| x * 2)
            .sum();
            // 编译为与手写循环同样高效的代码
            let mut sum_manual = 0;
            for &x in &numbers {
            if x % 2 == 0 {
            sum_manual += x * 2;
            }
            }
            println!("迭代器求和: {}", sum);
            println!("手动求和: {}", sum_manual);
            // 2. Option和Result的零成本处理
            fn safe_division(a: f64, b: f64) -> Option<f64> {
              if b == 0.0 {
              None
              } else {
              Some(a / b)
              }
              }
              let result = safe_division(10.0, 2.0)
              .map(|x| x * 2.0)
              .and_then(|x| safe_division(x, 3.0))
              .unwrap_or(0.0);
              println!("安全除法链式结果: {}", result);
              // 3. 模式匹配的零成本
              let value = Some(42);
              match value {
              Some(x) => println!("有值: {}", x),
              None => println!("无值"),
              }
              // 编译为高效的跳转表或条件判断
              }
              fn memory_layout_optimization() {
              println!("\n=== 内存布局优化 ===");
              use std::mem;
              // 1. 栈分配 vs 堆分配
              println!("内存使用分析:");
              // 栈分配的结构体
                #[derive(Debug)]
              struct StackData {
              a: i32,
              b: i32,
              c: i32,
              }
              // 堆分配的结构体
                #[derive(Debug)]
              struct HeapData {
              data: Vec<i32>,
                }
                let stack_instance = StackData { a: 1, b: 2, c: 3 };
                let heap_instance = HeapData { data: vec![1, 2, 3] };
                println!("栈结构体大小: {} 字节", mem::size_of_val(&stack_instance));
                println!("堆结构体大小: {} 字节", mem::size_of_val(&heap_instance));
                println!("向量容量: {}", heap_instance.data.capacity());
                // 2. 内存对齐优化
                  #[repr(C)]
                struct Unoptimized {
                a: u8,   // 1字节
                b: u32,  // 4字节
                c: u8,   // 1字节
                }
                  #[repr(C, packed)]
                struct Packed {
                a: u8,
                b: u32,
                c: u8,
                }
                let unopt = Unoptimized { a: 1, b: 2, c: 3 };
                let packed = Packed { a: 1, b: 2, c: 3 };
                println!("未优化结构体大小: {} 字节", mem::size_of_val(&unopt));
                println!("打包结构体大小: {} 字节", mem::size_of_val(&packed));
                // 3. 使用Box优化大类型
                struct LargeType {
                data: [u8; 1024], // 1KB数据
                }
                // 直接在栈上分配
                let stack_large = LargeType { data: [0; 1024] };
                // 在堆上分配
                let heap_large = Box::new(LargeType { data: [0; 1024] });
                println!("栈上大类型大小: {} 字节", mem::size_of_val(&stack_large));
                println!("堆上大类型大小: {} 字节", mem::size_of_val(&heap_large));
                // 4. 零大小类型优化
                struct Nothing;
                let nothing = Nothing;
                println!("零大小类型大小: {} 字节", mem::size_of_val(&nothing));
                // 包含零大小类型的结构体
                struct WithZST {
                data: i32,
                _marker: Nothing,
                }
                let with_zst = WithZST { data: 42, _marker: Nothing };
                println!("包含ZST的结构体大小: {} 字节", mem::size_of_val(&with_zst));
                }

通过本章的全面学习,你已经深入掌握了Rust最独特和强大的特性——所有权系统。从基本的所有权规则到高级的借用模式,从简单的切片使用到复杂的内存优化技巧,你现在应该能够编写出既安全又高效的Rust代码。在下一章中,我们将探讨结构体和方法,学习如何组织数据和行为。