枚举基础
> 理解枚举如何定义一组可能的值,掌握枚举变体的三种形式及其内存布局。
为什么需要枚举?
枚举语法
概念名称: 枚举定义一组可能的值,每个变体可选携带数据。
语法结构:
┌──────────────────────────────────────┐
│ enum 枚举名 { │
│ 变体1, // 无数据 │
│ 变体2(类型), // 元组形式 │
│ 变体3 { 字段: 类型 }, // 结构体形式│
│ } │
│ │
│ let 值 = 枚举名::变体; │
│ │
│ match 值 { │
│ 枚举名::变体1 => 处理1, │
│ 枚举名::变体2(x) => 处理2, │
│ _ => 默认处理, │
│ } │
└──────────────────────────────────────┘最简示例
rust
▶ Runenum Direction {
North,
South,
East,
West,
}
fn main() {
let dir = Direction::North;
match dir {
Direction::North => println!("向北"),
_ => println!("其他方向"),
}
}问题场景
rust
▶ Run// 问题:表示方向
// 方案 1:使用整数(不安全)
let direction: i32 = 0; // 0 代表什么?1、2、3 呢?
// 方案 2:使用字符串(不高效)
let direction: &str = "north"; // 可能拼写错误
// 方案 3:使用枚举(安全、高效)
enum Direction {
North,
South,
East,
West,
}
let direction = Direction::North; // 类型安全,有补全枚举的优势
┌─────────────────────────────────────────────────────┐
│ 枚举的优势 │
├─────────────────────────────────────────────────────┤
│ │
│ 1. 类型安全 │
│ • 只能是定义的几个值之一 │
│ • 编译器检查,防止无效值 │
│ │
│ 2. 表达力强 │
│ • 每个变体可以携带不同数据 │
│ • 可以精确描述状态 │
│ │
│ 3. 穷尽检查 │
│ • match 必须处理所有情况 │
│ • 添加新变体时,编译器提示更新代码 │
│ │
│ 4. 零成本抽象 │
│ • 和普通整数一样高效 │
│ • 没有运行时开销 │
│ │
└─────────────────────────────────────────────────────┘定义和创建枚举
基本语法
rust
▶ Run// 定义枚举
enum Direction {
North,
South,
East,
West,
}
fn main() {
// 创建枚举实例
let dir = Direction::North;
// 使用 match 处理
match dir {
Direction::North => println!("向北"),
Direction::South => println!("向南"),
Direction::East => println!("向东"),
Direction::West => println!("向西"),
}
}枚举的内存表示
enum Direction {
North, // 0
South, // 1
East, // 2
West, // 3
}
内存布局:
┌─────┐
│ 0 │ ← 用一个整数表示
└─────┘
大小:1 字节(可以用 u8 存储 4 个值)带数据的枚举变体
rust
▶ Runenum Message {
// 无数据
Quit,
// 命名字段(类似结构体)
Move { x: i32, y: i32 },
// 单个值
Write(String),
// 多个值(类似元组)
ChangeColor(i32, i32, i32),
}
fn main() {
// 创建不同变体
let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
let m3 = Message::Write(String::from("hello"));
let m4 = Message::ChangeColor(255, 0, 0);
// 每个变体可以携带不同类型和大小的数据
}带数据枚举的内存布局
enum Message {
Quit, // 无数据
Move { x: i32, y: i32 }, // 8 字节
Write(String), // 24 字节
ChangeColor(i32, i32, i32), // 12 字节
}
内存布局:
┌─────┬─────────────────────────────┐
│标签 │ 数据(最大变体) │
│2bit │ 24 字节 │
└─────┴─────────────────────────────┘
• 标签(tag):标识是哪个变体
• 数据区:足以容纳最大变体
• 总大小:约 32 字节小结
- 枚举定义一组可能的值,变体可以携带不同类型的数据
- 三种变体形式:无数据、元组形式
Variant(T)、结构体形式Variant { field: T } - 枚举内存:标签(标识变体)+ 数据区(容纳最大变体)
- match 必须穷尽所有变体,保证安全
练习题
详见:练习题