Rust 核心基础数据类型与变量系统
(2025–2026 视角,注重实用性与常见误区)
Rust 的类型系统和变量绑定规则是它“安全 + 高性能”特性的核心基石。
理解这些规则后,很多“为什么 Rust 这么写”“为什么报这个错”就瞬间清晰了。
一、Rust 的基本哲学(先记住这三条)
- 默认不可变(immutable by default)
- 所有权 + 借用(Ownership + Borrowing)贯穿始终
- 零成本抽象(zero-cost abstractions)——你付出的性能代价几乎为零
二、Rust 核心基础数据类型全览(2025 年无重大变化)
| 分类 | 类型 | 大小(典型 64 位系统) | 默认值 | 是否有符号 | 备注与常见用途 |
|---|---|---|---|---|---|
| 整数 | i8 / i16 / i32 / i64 / i128 | 1/2/4/8/16 字节 | — | 有 | 最常用 i32、i64 |
| 无符号整数 | u8 / u16 / u32 / u64 / u128 | 同上 | — | 无 | 字节、索引、位操作常用 u8/u32/u64 |
| 浮点数 | f32 / f64 | 4 / 8 字节 | — | — | 默认用 f64(精度更高) |
| 布尔 | bool | 1 字节 | false | — | if / match / while 的条件 |
| 字符 | char | 4 字节 | — | — | Unicode 标量值(’中’、’😊’ 都是 char) |
| 单元类型 | () | 0 字节 | () | — | 无返回值函数的返回类型 |
| 字符串切片 | &str | 指针 + 长度(16 字节) | — | — | 静态字符串字面量、字符串切片 |
| 拥有字符串 | String | 堆分配(24 字节元数据) | — | — | 可变、可增长的 UTF-8 字符串 |
| 数组 | [T; N] | N × size_of::() | — | — | 定长、在栈上 |
| 切片 | &[T] / &mut [T] | 指针 + 长度(16 字节) | — | — | 动态视图(Vec、数组、String 的切片) |
| 元组 | (T1, T2, …) | 各元素大小之和 + 对齐 | — | — | 多返回值、临时组合数据 |
| 指针 | *const T / *mut T | 8 字节 | — | — | unsafe 专用,不常用 |
三、变量声明与绑定规则(最容易出错的地方)
// 1. 默认不可变(immutable)
let x = 42; // x 是不可变的
// x = 100; // 编译错误!
let mut y = 100; // 显式声明可变
y = 200; // OK
// 2. 类型推导(type inference)非常强大
let a = 42; // 推导为 i32
let b = 3.14; // 推导为 f64
let c = '中'; // char
let d = "hello"; // &str
let e = String::from("world"); // String
// 3. 显式类型注解(当推导不出来或想明确时)
let f: u64 = 18446744073709551615;
let g: &str = "静态字符串";
let h: i32 = -2147483648;
// 4. 变量遮蔽(shadowing)——非常常用且强大
let x = 5;
let x = x + 1; // 新的 x,遮蔽了旧的 x
let x = x * 2; // 又一个新的 x
println!("x = {}", x); // 输出 12
// 5. 常量(const)与静态变量(static)
const MAX_POINTS: u32 = 100_000; // 编译期常量,可用于数组长度
static VERSION: &str = "1.82.0"; // 全局静态(有 'static 生命周期)
// 注意:static mut 是 unsafe 的,很少用
四、所有权与借用规则(Rust 灵魂三问)
| 规则 | 代码示例 | 含义与后果 |
|---|---|---|
| 每个值有且仅有一个所有者 | let s1 = String::from(“hello”); let s2 = s1; | s1 失效,s2 接管所有权(移动语义) |
| 离开作用域时自动 drop | { let s = String::from(“hi”); } | s 出作用域 → drop → 内存释放 |
| 同一时刻只能有一个可变借用 | let mut s = String::from(“hello”); &mut s; &mut s; | 编译错误!不能同时有多个 &mut |
| 可变借用与不可变借用冲突 | let r1 = &s; let r2 = &mut s; | 编译错误!不可变借用期间不能有可变借用 |
| &T 可以多个同时存在 | let r1 = &s; let r2 = &s; let r3 = &s; | 允许多个不可变引用 |
五、常见类型转换与常用方法(实战高频)
// 数值类型转换(安全方式)
let x: i32 = 42;
let y: i64 = x as i64; // 显式转换(可能截断)
let z: u32 = x.try_into().unwrap(); // 推荐:使用 try_into
// String 与 &str 互转
let s = String::from("hello");
let s_ref: &str = &s; // &String → &str(自动解引用)
let s_owned: String = s_ref.to_string(); // &str → String(克隆)
let s2 = s_ref.to_owned(); // 同上
// 字符串格式化(类似 Python f-string)
let name = "重阳";
println!("Hello, {name}!");
println!("当前年份:{}", 2026);
// Option 与 Result(错误处理基石)
let some_num = Some(42);
let none_val: Option<i32> = None;
let result: Result<i32, &'static str> = Ok(100);
let err: Result<i32, &'static str> = Err("出错了");
六、2025–2026 年最常被问的 10 个“为什么”问题
- 为什么
let x = 5; x = 10;会报错?
→ 默认不可变,必须写mut - 为什么
let s2 = s1;后 s1 就不能用了?
→ 移动语义(Move),所有权转移 - 为什么
String可以变,&str不可以?
→String拥有堆内存,&str是借用(不可变视图) - 为什么数组长度必须是常量?
→[T; N]的 N 必须在编译期知道(const 或 const fn) - 为什么
&mut self方法叫可变借用?
→ 因为它借用了self的可变权限 as和try_into()有什么区别?
→as不检查溢出,try_into()返回 Result(更安全)- 为什么
String::from("hello")和"hello".to_string()都可以?
→ 都是把&str转为拥有所有权的String let x = 5; let y = x;为什么不会移动?
→ 基本类型实现了Copytrait(栈上复制)- 生命周期
'a到底是什么?
→ 借用能活多久的约束(后面会专门讲) - 为什么 Rust 不需要 GC?
→ 编译期通过所有权 + 借用规则静态确定何时 drop
总结一句话(可以直接背)
Rust 的类型与变量系统核心就是一句话: “每个值都有唯一的所有者,默认不可变,通过所有权转移和借用规则严格管理内存安全。”
想继续深入哪个部分?
- 所有权、借用、生命周期三件套详细拆解
- Copy vs Clone trait 区别与使用场景
- Option / Result 实战用法(? 操作符、unwrap_or 等)
- 字符串三种形态(&str、String、&String)的正确使用姿势
- 数组 / Vec / slice 的常用操作对比
- 或者直接来一道 LeetCode 题的 Rust 写法示范
告诉我你的下一步想重点搞懂哪一块~