目标
理解 Rust 独特的所有权、借用与生命周期机制,能写稍复杂程序。
1. 所有权系统(Ownership)
Rust 的核心理念是内存安全:每个值在任意时刻只能有一个所有者,所有者离开作用域时,值会被释放。
fn main() {
let s1 = String::from("hello"); // s1 拥有这个字符串
let s2 = s1; // 移动(Move),s1 不再有效
// println!("{}", s1); // 错误!s1 已被移动
println!("{}", s2);
}
克隆(Clone) :
let s1 = String::from("hello");
let s2 = s1.clone(); // 显式克隆,s1 仍然可用
println!("s1 = {}, s2 = {}", s1, s2);
可变性
let mut x = 5;
x += 1;
println!("{}", x);
2. 借用与引用
Rust 允许临时借用值,而不转移所有权。
不可变引用
fn main() {
let s = String::from("hello");
let len = calculate_length(&s); // 借用 s
println!("长度: {}", len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
可变引用
fn main() {
let mut s = String::from("hello");
change(&mut s);
println!("{}", s);
}
fn change(s: &mut String) {
s.push_str(", world");
}
借用检查器规则
- 在同一时间,只能有一个可变引用,或多个不可变引用
- 防止数据竞争
3. 生命周期(Lifetimes)
生命周期确保引用在有效范围内使用。
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 = String::from("world");
let result = longest(&s1, &s2);
println!("最长的是 {}", result);
}
'a表示引用的生命周期- 生命周期也可以用于结构体:
struct Book<'a> {
title: &'a str,
}
4. 结构体与枚举
结构体
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
fn main() {
let rect = Rectangle { width: 30, height: 50 };
println!("面积: {}", rect.area());
}
枚举
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
Option 与 Result
let some_number: Option<i32> = Some(5);
let no_number: Option<i32> = None;
let result: Result<i32, &str> = Ok(10);
let error: Result<i32, &str> = Err("出错了");
5. 集合与迭代器
Vec
let mut v = vec![1, 2, 3];
v.push(4);
for i in &v {
println!("{}", i);
}
HashMap
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert("Alice", 10);
scores.insert("Bob", 20);
迭代器和高阶函数
let v = vec![1, 2, 3, 4];
let v2: Vec<_> = v.iter().map(|x| x * 2).collect();
println!("{:?}", v2); // [2,4,6,8]
6. 错误处理
panic! 宏
panic!("程序出错!");
Result<T, E>
use std::fs::File;
fn main() -> std::io::Result<()> {
let f = File::open("hello.txt")?;
Ok(())
}
unwrap / expect / ?
let f = File::open("hello.txt").expect("无法打开文件");
练习建议
- 命令行记账程序
- 输入金额和备注,保存到
Vec或文件中 - 统计总金额
- 保存/读取文件
- 文件读取与写入
use std::fs;
fn main() {
let contents = fs::read_to_string("data.txt").expect("读取失败");
println!("文件内容:\n{}", contents);
}