Rust 课件速查 · 第1页

Ch01 初见Rust
Rust四大工具
rustup  工具链管理  cargo  项目构建(new/build/run/test/check/clean/doc)
rustc  编译器      rustdoc 文档生成
cargo new hello
[package] name="hello" version="0.1.0" edition="2021"
[dependencies]

fn main() { println!("Hello, world!"); }
GCD 函数 — mut参数 / 类型推断 / 最后表达式返回值 / assert!
fn gcd(mut n: u64, mut m: u64) -> u64 {
    assert!(n != 0 && m != 0);             // 假→panic
    while m != 0 {                         // 条件无需括号
        if m < n { let t = m; m = n; n = t; } // let自动推断
        m = m % n;
    }
    n                                       // 最后无分号=返回值
}
测试 — #[test] attribute / assert_eq! / cargo test
#[test]
fn test_gcd() {
    assert_eq!(gcd(14, 15), 1);
    assert_eq!(gcd(2*3*5*11*17, 3*7*11*13*19), 3*11);
}
命令行 GCD — env::args / FromStr / Vec / 解引用*
use std::env;
use std::str::FromStr;
fn main() {
    let mut nums = Vec::new();
    for arg in env::args().skip(1) {         // 跳过程序名
        nums.push(u64::from_str(&arg).expect("err")); // 解析→失败panic
    }
    if nums.len() == 0 {
        eprintln!("usage: gcd n1 n2 ..");  // →stderr
        std::process::exit(1);
    }
    let mut d = nums[0];
    for m in &nums[1..] { d = gcd(d, *m); }  // &引用 *解引用
    println!("GCD={}", d);
}
变量 — immutable默认 / mut / shadowing / 代码块值
let x = 5;       let mut x = 5; x = 6;
let x = 5; let x = x + 1;
{ let x = x * 2; } let y = { let z = x * x; z / 2 };
(-4_i32).abs()  -4_i32.abs()
Ch02 基础类型
14种定宽数字类型 / usize/isize = 内存地址宽度
u8 u16 u32 u64 u128 usize    i8 i16 i32 i64 i128 isize    f32 f64
整数字面量 / byte literal
0x_0fff_ffff_i32   0o1670isize   0b11110000u8
b'A' = 65u8   b'\x41' = 65u8   b'\n' = 10u8
补码: 正数原=反=补 负数补=反+1(符号位参与) 计算机用补码 i8[-128,127]
as三规则: ①位不变→原样 ②变短→截高位 ③变长→符号位填充(无符=0) 无隐式转换!
1000_i16 as i8 → -24_i8
-1_i16   as i32 → -1_i32
65535_u16 as i32 → 65535_i32
溢出控制: checked→Option / wrapping(回绕) / overflowing→(v,bool) / saturating(钳)
100_u8.checked_add(200) → None
500_u16.wrapping_mul(500) → 53392
255_u8.overflowing_add(2) → (1, true)
32760_i16.saturating_add(10) → 32767
浮点 IEEE754 f64::NAN != f64::NAN INFINITY NEG_INFINITY is_nan() consts::PI
bool:1B true as i32→1 char:4B Unicode 仅u8 as char tuple:1元组必(v,) 0元组=() t.0,t.1
指针 &T(copy只读) &mut T Box<T> *mut/*const T(仅unsafe) Array[T;N]栈 Vec堆(ptr+len+cap) Slice胖指针
String=Vec<u8> UTF-8 .len()→字节数 .chars().count()→字符数 不可z[0]索引 r"raw" r###"#"### b"GET"
内存: 每线程独立栈(LIFO,stack frame) 进程共享堆 type Bytes = Vec<u8>; size_of::<i32>()→4
编码: 正问题 2^(k-1)<m≤2^k 反问题 长度k→2^k 内存地址宽度k→管理2^k字节
优先级>一元负号: (-4).abs()≠-4.abs() u16::pow(2,4)=16 浮点字面量: 整数部分必须写 小数/指数/后缀至少一个 无后缀默认f64
内存四概念: Value(Type+ByteRepr) / Place(内存位置) / Variable(栈命名slot) / Pointer(存地址的Value)
Ch03 所有权与所有权转移
三原则: ①每值唯一owner ②离scope→自动drop(逆序) ③move后原owner不可用(E0382)
四扩展: Move转移 / Copy豁免 / Rc共享 / Borrow借用 成本: Py(引用计数+GC) C++(深拷) Rust(仅拷栈)
Move触发: 赋值/传参/返回/元组/for迭代non-copy 条件if move→变量失效(保守) 循环需重赋值
let s1 = String::from("hello");
let s2 = s1;        // s1所有权→s2 s1无效→E0382
不能v[2]移所有权→E0507 5种移出: remove swap_remove pop replace take Option模式
v.remove(i)       v.swap_remove(i)
v.pop()           std::mem::replace(&mut v[i], new)
std::mem::take(&mut v[i])  vec![Some(v), None]
Copy豁免: 数字/char/bool/全Copy复合 #[derive(Copy,Clone)]需全字段Copy
Rc共享所有权 — 引用计数 / 非线程安全 / Arc线程安全 / 不可修改
use std::rc::Rc;
let s: Rc<String> = Rc::new(String::from("hi"));
let t = s.clone();       // ref count=2
let u = Rc::clone(&s);   // ref count=3  count→0堆释放
Ch04 引用 & 解引用
&T:copy只读多共存 &mut T:non-copy读写最多一互斥 目的: 编译期"读不打扰,写独占"
let r = &value;       // &T  copy type  共享引用
let rm = &mut value; // &mut T  non-copy  可变引用
*rm = 456;            // 解引用: 通过&mut修改指向的值
解引用 * — 显式deref / 自动deref / Deref Coercion
// * 显式解引用: 从引用访问到它所指向的值
let value: i32 = 123;
let refer = &value;
let v2: i32 = *refer;       // *refer → 123
assert_eq!(value, *refer);

// . 操作符自动deref: 编译器自动插入* 对Box/Rc也适用
let b = Box::new(String::from("hi"));
b.len();                     // 自动 *b → String 再 .len()  不需写(*b).len()
let rc = Rc::new(42);
rc.count_ones();             // 自动 *rc → i32 再 .count_ones()

// . 操作符会自动ref: 调用&self方法时自动取引用
let v = vec![1,2,3];
v.len();                     // 自动 (&v).len()  Vec::len(&self)

// Deref Coercion (隐式转换): 编译器在特定位置自动插入deref
// &String → &str  &Vec<T> → &[T]  &Box<T> → &T  &mut T → &T
fn show(s: &str) { .. }
let name = String::from("hi");
show(&name);                 // &String 自动转 &str  (Deref trait: String→str)
引用赋值=重绑定(非修改指向值) ==透明比值 ptr::eq比地址 Option<&T>表示空引用(无null)
Lifetime: x ≥ &x ≥ 使用处 引用不可比所指值活更久 'static=全程
Elision: ①每参独立lifetime ②1输入→赋输出 ③&self→赋输出 struct含引用须声明S<'a>
smallest — 返回引用 + elision自动补全lifetime
fn smallest(v: &[i32]) -> &i32 {  // 返回引用 elision自动补全
    let mut s = &v[0];
    for r in &v[1..] { if *r < *s { s = r; } }
    s
}
STASH — 'static lifetime / 共享可变铁律 / 四引用vs C
static mut STASH: &i32 = &0;
fn stash(r: &'static i32) { unsafe { STASH = r; } }
共享→"冰冻"owner不能改 可变→独占owner无法访 所有权≠可变性
四引用vs C: &T↔const T* &mut T↔T* Box↔unique_ptr *mut↔T*(unsafe)
Ch05 表达式
Rust是表达式语言 — 几乎一切有值 ;变语句(值=()) 代码块值=最后无分号表达式
let x = if cond { 1 } else { 0 };
match code { 0 => println!("OK"), _ => println!("Unknown") }
if let Some(v) = opt { .. } else { .. }
while cond {..}   while let Some(v) = iter.next() {..}
for &e in &v {..}   0..5  0..=5
loop { break val; }   'outer: loop { break 'outer v; }
return expr;   let name: type = expr;
操作符: 无++/-- 按位取反!(非~) 无a=b=3 %适用整+浮 位优先级>比较 && ||短路须bool
as:宽→窄截 有符→宽扩符号 浮→整向0取 Deref Coercion: &mut T→&T &String→&str &Vec→&[T] &Box→&T
let声明不初始化: 赋值前不能读→E0381 if let=match语法糖 while let遇None自动停止 return expr默认()
Ch06 错误处理
内部错误(逻辑bug)→panic! 外部错误(不可控)→Result<T,E>
Unwinding(默认): ①打印 ②栈逆序drop ③线程退出 安全有序不产悬空指针 Abort: -C panic=abort
Result方法族 (除is_ok/is_err外均消费所有权 as_ref/as_mut避免)
enum Result<T, E> { Ok(T), Err(E) }
rst.is_ok()  rst.is_err()  rst.unwrap()  rst.expect(msg)
rst.unwrap_or(fb)  rst.unwrap_or_else(f)  rst.ok()  rst.err()
rst.as_ref()→Result<&T, &E>  rst.as_mut()→Result<&mut T, &mut E>
?操作符 = match{Ok→v, Err→return Err.into()} 自动From::from转换 链式a()?.b()?.c()?
let v = foo(...)?;
fn main() -> Result<(), Box<dyn std::error::Error>> { Ok(()) }
多错误: 自定义enum+impl From(推荐) 或 Box<dyn Error>(快速) Error trait: {}/{:?}/to_string可打印 source()可追溯
Ch07 Crates & Modules
Crate: binary(main.rs) / library(lib.rs) Module: mod name{} 或 a.rs / a/mod.rs Package: Cargo.toml
路径: crate::a::b(绝对) self::x super::y 5级可见性: private / pub(crate) / pub(super) / pub(in) / pub
use a::{b,c}; use d as e; pub use重导出 struct字段独立可见性
测试: #[test]+assert!族 单元#[cfg(test)]mod tests{} 集成tests/目录 cargo test pat -- --nocapture
文档: ///项 //!模块 cargo doc ```ignore ```no_run ```should_panic doc-test编译运行代码块
依赖: [dependencies] name="ver" SemVer MAJOR.MINOR.PATCH ^1.2.3 ~1.2.3 Cargo.lock cargo update
Workspace: [workspace] members=["p1","p2"]共享target/和Cargo.lock 多binary: src/bin/*.rs
Attributes: #[warn/allow/deny] #[cfg(unix)] #[repr(C/align/packed)] #[inline] #![..]inner
模块"硬壳": use不能穿透私有模块 pub use重导出打破硬壳 prelude自动导入Vec String Option等
doc-test: cargo test运行 ```→编译运行 ```ignore→不编译 ```no_run→编译不运行
Ch09 Enum
三种Variant: Unit(A) / Tuple(B(i32,String)) / Struct(C{x:f64}) 内存:tag+data定长#[repr(C)]
enum E { A, B(i32, String), C{x: f64, y: f64} }
C-style:值=整数(0编号) as→整数 反向自定义 泛型 Option<T>{Some,None} Result<T,E>{Ok,Err}
Option优化: Option<Box<i32>>仅1 isize (0=None 非0=ptr) 利用Rust无null pointer
Ch10 Pattern
10种: Literal/Variable(非Copy→所有权转移)/Wildcard(_)/Tuple(a,b)/Struct(P{x,..})/Array/Slice/ref/ref mut/&
Guard: pat if cond 多重: A|B @绑定: pat@subpat 场景: match/let/if let/while let/for/参数 穷尽性E0004
解构非Copy→所有权转移 用ref避免 越具体越靠前
match RoughTime::to_english() — 字面量优先级>变量绑定
match self {
    InThePast(TimeUnit::Hour, 1) => format!("an hour ago"),      // 最具体
    InThePast(unit, 1)           => format!("a {} ago", unit.singular()),
    InThePast(unit, count)        => format!("{} {} ago", count, unit.plural()),
    JustNow                       => format!("just now"),
    InTheFuture(unit, count)      => format!("{} {} from now", count, unit.plural()),
}
Ch08 结构体
三种Struct / 简写P{x,y} / update P{..other} / 部分移动
struct P { x: f64, y: f64 }
struct C(u8, u8, u8);
struct U;
impl块 — type-associated(::调用) / method(.调用, &self=&mut self=self=Box<Self>=Rc<Self>)
impl P {
    fn new(x: f64, y: f64) -> Self { P{x, y} }
    fn len(&self) -> f64 { (self.x.powi(2) + self.y.powi(2)).sqrt() }
    const ZERO: P = P{x: 0.0, y: 0.0};
}
泛型Queue<T> + impl 定特化impl Queue<f64> Lifetime: struct E<'a>{r:&'a[i32]}
struct Queue<T> { older: Vec<T>, younger: Vec<T> }
impl<T> Queue<T> {
    fn new() -> Self { Queue { older: vec![], younger: vec![] } }
    fn push(&mut self, v: T) { self.younger.push(v); }
    fn pop(&mut self) -> Option<T> {
        if self.older.is_empty() { self.younger.reverse();
            self.older.append(&mut self.younger); }
        self.older.pop()
    }
}
内部可变性 Cell<T>:T:Copy get()/set(v)编译期零开销 不能取内部引用只能整体替换单线程
RefCell<T>: borrow()→Ref borrow_mut()→RefMut 运行时检查(违反→panic)单线程
Orphan Rule: impl外部trait for外部类型→禁止 derive: Debug Clone Copy PartialEq Eq Hash Default Ord
Ch11 Trait & Generic
Trait≈Java Interface: impl Trait for Type{} 须use Trait才能调方法 trait可继承trait B:A{}
Trait Object: &dyn Trait 动态(vtable) 胖指针(ptr+vtable) Trait Bound: <T:Trait> 静态(单态化)零开销
impl Trait语法糖≡<T:Trait> where: fn<T,U>(x:T,y:U) where T:Clone+Debug, U:PartialEq{..}
泛型Trait三形式: ①类型参数Add<Rhs=Self>→多种实现 ②关联类型Iterator<Item>→一种实现 ③关联常量
Self=当前类型 Fully Qualified: <Type as Trait>::method() 闭包: ||{} move||{} Fn/FnMut/FnOnce
Orphan Rule: 只能在类型或trait所在crate中impl &T/&mut T/Box例外
Object Safety: ①不用Self:Sized ②无泛型方法 ③不返回/消耗Self(除Box<Self>) where Self:Sized→对obj不可见
Sized:编译期已知大小 [T]和dyn Trait是!Sized(DST) ?Sized放宽 prelude自动导入Vec String Option等
Send:跨线程转移所有权 Rc/RefCell不是Send Arc/Mutex是 Sync:跨线程共享引用 Cell/RefCell不是Sync
默认实现不满意可在impl中重写 Self=实现trait的类型 单态化=编译期为每个具体T生成独立代码
Fully Qualified 4场景: 方法冲突/关联函数/外部trait/类型推断不够
Ch12 Operator Overloading
一个运算符↔一个Trait中的一个方法 只需在自定义类型上impl对应trait即可
// 四种等价调用 — 运算符形式不需要use Add  方法形式需要
10_i32 + 32_i32                                    // 运算符形式
10_i32.add(32_i32)                                  // 方法调用(需 use std::ops::Add)
std::ops::Add::add(10_i32, 32_i32)                  // Qualified Method Call
<i32 as std::ops::Add>::add(10, 32)             // Fully Qualified Method Call
运算符→Trait对照表
算术:  +→Add(add)  -→Sub(sub)  *→Mul(mul)  /→Div(div)  %→Rem(rem)
位:    &→BitAnd  |→BitOr  ^→BitXor  !→Not  <<→Shl  >>→Shr
一元:  -→Neg  !→Not
复合:  +=→AddAssign  -=→SubAssign ...  (与二元不同trait! 各需单独impl)
比较:  == != → PartialEq(eq,ne默认) / Eq(标记自反性)   < <= > >= → PartialOrd(partial_cmp→Option<Ordering>) / Ord
索引:  a[i] → Index(index→&Output)  a[i]=v → IndexMut(index_mut→&mut Output)
Add trait 结构 — Rhs类型参数 + Output关联类型
pub trait Add<Rhs = Self> {       // Rhs=右侧操作数类型 默认=Self
    type Output;                    // 关联类型: 加法结果的类型
    fn add(self, rhs: Rhs) -> Self::Output;
}
为Complex<T>实现Add — 泛型 + where约束 逐步泛化过程
// Step1: 特化 Complex<f64>
impl Add for Complex<f64> { type Output = Self; fn add(self, r: Self) -> Self::Output {..} }
// Step2: 泛化  T+T=T → Complex<T>+Complex<T>=Complex<T>
impl<T> Add for Complex<T> where T: Add<Output = T> {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        Complex { re: self.re + rhs.re, im: self.im + rhs.im }
    }
}
// Step3: 更宽松  L+R=O → Complex<L>+Complex<R>=Complex<O>
impl<L, R> Add<Complex<R>> for Complex<L> where L: Add<R> { type Output = Complex<L::Output>; .. }
// 引用版本: impl Add for &Complex<T> 或用 &'a T: Add<&'b T> 放松lifetime约束
PartialEq vs Eq — Partial缺自反性(f64::NAN≠NAN) Eq标记自反性成立
// Complex<i32>✅Eq  Complex<f32>❌Eq (因f32不满足自反性)
// PartialOrd: f32/f64是标准库仅有的不实现Ord的类型(NAN→None不可比)
// derive: #[derive(PartialEq,Eq,PartialOrd,Ord)]需所有字段已实现对应trait
Index / IndexMut — a[i] ≡ *a.index(i) a[i]=v ≡ *a.index_mut(i)=v
impl<P> Index<usize> for Image<P> {
    type Output = [P];
    fn index(&self, row: usize) -> &[P] {
        let start = row * self.width;
        &self.pixels[start..start + self.width]
    }
}
不可重载: ? && || .. ..= & = f(x) 可重载: .(Deref) *(DerefMut) 复合赋值与二元是不同的trait!

Rust 课件速查 · 第2页

完整代码示例
Ch01 — GCD + 测试 + 命令行
fn gcd(mut n: u64, mut m: u64) -> u64 {
    assert!(n != 0 && m != 0);
    while m != 0 { if m < n { let t = m; m = n; n = t; } m = m % n; }
    n
}
#[test] fn test() { assert_eq!(gcd(14, 15), 1); }
Ch03 — Copy vs Move / replace / take
// Copy (i32) — 复制值
let n1: i32 = 36;  let n2 = n1;  // n1仍然可用

// Non-Copy (String) — 所有权转移
let s1 = String::from("dog");  let s2 = s1;  // s1无效! E0382

// 从Vec移出元素
let mut v = vec![String::from("a"), String::from("b")];
let e = std::mem::replace(&mut v[0], String::from("x")); // v→["x","b"] e="a"
let e = std::mem::take(&mut v[0]); // v→["","b"] e="x" (String Default="")
Ch03 — Rc共享所有权
use std::rc::Rc;
let s: Rc<String> = Rc::new(String::from("Hello World!"));
let t = s.clone();
let u = Rc::clone(&s);
Ch04 — smallest返回引用 + STASH
fn smallest(v: &[i32]) -> &i32 {
    let mut s = &v[0];
    for r in &v[1..] { if *r < *s { s = r; } }
    s
}
static mut STASH: &i32 = &0;
fn stash(r: &'static i32) { unsafe { STASH = r; } }
Ch05 — if let / while let / match / labeled break
// if let — match语法糖  只关心一个pattern
if let Some(v) = option_value { println!("{}", v); } else { println!("none"); }

// while let — 遇None自动停止
while let Some(s) = a[i] { rst.push(s); i += 1; }

// match — 穷尽性检查 + 模式解构
let name = match optional_name {
    Some(v) => v,
    None => String::from("Stranger")
};

// loop + labeled break 返回值
let sqrt = 'outer: loop {
    n += 1;
    for i in 1.. { let sq = i * i;
        if sq == n { break 'outer i; }
        if sq > n { break; }
    }
};
Ch06 — Result + ?链 / 多错误传播
// ? 操作符 — Err时提前return 自动From::from转换错误
fn read_file() -> Result<String, std::io::Error> {
    let mut s = String::new();
    File::open("hello.txt")?.read_to_string(&mut s)?;
    Ok(s)
}

// 自定义错误类型 + impl From → ?自动转换
enum MyError { Io(std::io::Error), Parse(std::num::ParseIntError) }
impl From<std::io::Error> for MyError { fn from(e: std::io::Error) -> Self { MyError::Io(e) } }
impl From<std::num::ParseIntError> for MyError { fn from(e: std::num::ParseIntError) -> Self { MyError::Parse(e) } }

fn process() -> Result<i32, MyError> {
    let s = std::fs::read_to_string("data.txt")?; // io::Error→MyError::Io
    let n: i32 = s.trim().parse()?;                // ParseIntError→MyError::Parse
    Ok(n)
}
Ch08 — 泛型Queue<T> + impl
struct Queue<T> { older: Vec<T>, younger: Vec<T> }
impl<T> Queue<T> {
    fn new() -> Self { Queue { older: vec![], younger: vec![] } }
    fn push(&mut self, v: T) { self.younger.push(v); }
    fn pop(&mut self) -> Option<T> {
        if self.older.is_empty() { self.younger.reverse();
            self.older.append(&mut self.younger); }
        self.older.pop()
    }
}
Ch08 — Cell / RefCell 内部可变性
use std::cell::Cell;
let c = Cell::new(42); c.set(c.get() + 1);
use std::cell::RefCell;
let rc = RefCell::new(String::from("hi"));
*rc.borrow_mut() = String::from("hey");
Ch11 — 完整Trait示例: std::io::Write (含默认实现write_all)
pub trait Write {
    fn write(&mut self, buf: &[u8]) -> Result<usize>;  // 必须实现
    fn flush(&mut self) -> Result<()>;                  // 必须实现
    fn write_all(&mut self, buf: &[u8]) -> Result<()> {   // 默认实现
        let mut n = 0;
        while n < buf.len() { n += self.write(&buf[n..])?; }
        Ok(())
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> {..}  // 默认实现
}use std::io::Write;
struct Sink;
impl Write for Sink {
    fn write(&mut self, buf: &[u8]) -> Result<usize> { Ok(buf.len()) }
    fn flush(&mut self) -> Result<()> { Ok(()) }
}
let mut sink = Sink;
sink.write_all("hello".as_bytes())?;
Ch12 — Complex<T> 实现Add运算符
use std::ops::Add;
struct Complex<T> { re: T, im: T }
impl<T> Add for Complex<T> where T: Add<Output = T> {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        Complex { re: self.re + rhs.re, im: self.im + rhs.im }
    }
}
所有权·借用·生命周期 核心规则
Ownership  每值唯一owner 离scope→drop(逆序)  move后原owner不可用(E0382)
Borrow     &T:共享只读多共存,copy  &mut T:独占读写最多一  两者互斥
Lifetime   引用不可比所指值活更久  elision自动补全  'static=全程
Copy       赋值复制值(非move)  数字/char/bool/全Copy数组元组
Clone      .clone()深拷贝  非Copy也可实现
Drop       离scope自动调  创建逆序释放  可drop(v)提前
Move       赋值/传参/返回/元组/for迭代non-copy  条件if→变量失效
Partial Move  单独移走struct某字段  其余仍可用
Sized      编译期已知大小  [T]和dyn Trait是!Sized(DST)  ?Sized放宽
Send       可跨线程转移所有权  Rc/RefCell不是Send  Arc/Mutex是
Sync       可跨线程共享引用  T:Sync iff &T:Send  Cell/RefCell不是Sync
关键代码示例 (从col4移入)
Ch02 — as转换 / 溢出控制
assert_eq!( 1000_i16 as i8,   -24_i8);      // 截断溢出
assert_eq!(   -1_i16 as i32,   -1_i32);     // 符号扩展
assert_eq!(10_u8.checked_add(20), Some(30));
assert_eq!(500_u16.wrapping_mul(500), 53392);
println!("{}", f64::NAN == f64::NAN); // false!
Ch04/09 — Lifetime struct / JSON Enum
struct Extrema<'elt> { greatest: &'elt i32, least: &'elt i32 }
enum Json { Null, Number(f64), String(String), Array(Vec<Json>),
    Object(Box<HashMap<String, Json>>) }  // Box打破递归大小
Ch11 — Trait Object vs Generic
fn draw_dyn(shapes: &[Box<dyn Draw>]) {..}  // 动态 vtable 可存多种类型
fn draw_gen<T: Draw>(shapes: &[T]) {..}        // 静态 单态化 零开销
fn<T, U>(x: T, y: U) -> T where T: Clone + Debug, U: PartialEq {..}
标准库重难点方法
Vec<T> — 堆变长数组(ptr+len+cap)  越界索引→panic
v.push(x)                  末尾加元素
v.pop() -> Option<T>       末尾弹出
v.insert(i, x)             i位插入 后续元素后移 O(n)
v.remove(i) -> T           i位移除 后续元素前移 O(n)
v.swap_remove(i) -> T      末位替换i位 低成本 无序
v.len() / v.capacity()     当前长度/容量  len≤cap
v.sort() / v.reverse()     排序/反转  T:Ord

HashMap<K,V> — 哈希表  K:Eq+Hash
map.insert(k, v)           插入 返回旧值Option<V>
map.get(&k) -> Option<&V>  查询 返回引用
map.remove(&k) -> Option<V> 删除+返回
map.entry(k).or_insert(v)  占位:有则返&mut V 无则插入v

String — Vec<u8> UTF-8变长  .len()→字节数! .chars().count()→字符数
s.push(c) / s.push_str(ss) 追加字符/字符串
s.pop() -> Option<char>    弹出末尾字符
s.insert(i, c)             i位插入 越界→panic
&str — 切片引用 不可变
s.parse::<T>() -> Result<T,E>  字符串解析为数字等
s.split(p) / s.trim()      分割迭代器 / 去首尾空格

Option<T> — Some(T)|None 替代null
opt.unwrap() -> T          None→panic!
opt.expect("msg") -> T     None→panic+msg
opt.unwrap_or(def) -> T    None→默认值def
opt.map(|x|..) -> Option<U> Some→变换 None→None
opt.and_then(|x|..) -> Opt<U> Some→f(x) None→None(不嵌套)
opt.as_ref() -> Option<&T>  &Option→Option<&T> 避免消费
opt.take() -> Option<T>    取走值 原位变None
opt?                        None→return None

Result<T,E> — Ok(T)|Err(E)  ?=Err→return Err.into()
r.unwrap()/expect("msg")   Err→panic! 消费所有权
r.map(|x|..) -> Result<U,E> Ok→变换 Err不变
r.map_err(|e|..) -> R<T,F> Err→变换 Ok不变
r.and_then(|x|..) -> R<U,E> Ok→f(x) Err不变(不嵌套)
r.as_ref() -> Result<&T,&E>  避免消费  &Result→Result<&T,&E>

迭代器 — 惰性(不触发求值) 消费者触发求值
.iter()/.iter_mut()/.into_iter()  不可变/可变/所有权迭代
.map(|x|..) .filter(|x|bool)     变换/过滤(惰性)
.collect::<Vec<_>>() .fold(init,|a,x|..) 收集/折叠(消费)
.enumerate() .zip(other)          加索引/拉链
.find(|x|bool) .any(|x|bool) .all(|x|bool) 查找/任一/全满足(消费)
(0..n) (0..=n)                    左闭右开/闭区间
Cargo 命令 / 宏 / 属性
cargo new <name> [--lib]     cargo build [--release]     cargo run [-- args]
cargo check                   cargo test [pat] [-- --nocap] cargo doc [--open]
cargo clean                   cargo update                 cargo fmt / clippy
cargo publish [--dry-run]     RUST_BACKTRACE=1 cargo run

println!("{}",x)  eprintln!("err")  format!("x={x}")  assert!(cond)  assert_eq!(a,b)
panic!("msg")  todo!()  unreachable!()  vec![a,b,c]  vec![v;100]  dbg!(&x)
include_str!("f")  concat!(a,b)  matches!(expr,pat)

#[derive(Debug,Clone,Copy,PartialEq,Eq,Hash,Default,PartialOrd,Ord)]
#[test] #[should_panic] #[ignore]  #[allow/warn/deny(x)]
#[cfg(target_os="linux")] #[cfg(debug_assertions)] #[repr(C/align(N)/packed)]
#[inline] #[cold]  #![crate_type="lib"]

Cargo.toml:
[package] name version(MAJOR.MINOR.PATCH) edition("2021")
[dependencies] name="ver" (^1.2.3兼容1.x  ~1.2.3兼容1.2.x  >=1.2,<2.0)
[dev-dependencies] [build-dependencies] [profile.dev] opt-level=0 [profile.release] opt-level=3
[workspace] members=["p1","p2"]
常见编译错误
E0382  use of moved value            E0507  cannot move out of index
E0597  does not live long enough     E0502  cannot borrow immut + mut
E0506  cannot assign (borrowed)      E0384  assign twice to immutable
E0308  mismatched types              E0004  non-exhaustive patterns
E0277  trait bound not satisfied     E0204  trait Copy may not be impl'd
E0604  only u8 can cast as char      E0606  casting bool as f32 invalid
E0054  cannot cast as bool           E0596  cannot borrow (Rc) as mut
E0608  cannot index into a value     E0594  cannot assign to *refer (& ref)
E0381  use of possibly-uninit var
考试真题 — 所有权+借用+Lifetime
fn main() {
    let mut v = vec![String::from("a"), String::from("b")];
    let r = &v[0];
    v.push(String::from("c"));
    println!("{}", r);
}
答: 编译失败 E0502。r=&v[0]创建共享引用(lifetime至println!); v.push需&mut self; 共享+可变不能共存。
修法: println!移到push前→NLL让r在println!后自动结束→push可获可变引用。