Skip to content

枚举基础

> 理解枚举如何定义一组可能的值,掌握枚举变体的三种形式及其内存布局。

为什么需要枚举?

枚举语法

概念名称: 枚举定义一组可能的值,每个变体可选携带数据。

语法结构:
┌──────────────────────────────────────┐
│  enum 枚举名 {                        │
│      变体1,              // 无数据    │
│      变体2(类型),        // 元组形式  │
│      变体3 { 字段: 类型 }, // 结构体形式│
│  }                                    │
│                                       │
│  let 值 = 枚举名::变体;               │
│                                       │
│  match 值 {                           │
│      枚举名::变体1 => 处理1,          │
│      枚举名::变体2(x) => 处理2,       │
│      _ => 默认处理,                   │
│  }                                    │
└──────────────────────────────────────┘

最简示例

rust
enum Direction {
    North,
    South,
    East,
    West,
}

fn main() {
    let dir = Direction::North;
    match dir {
        Direction::North => println!("向北"),
        _ => println!("其他方向"),
    }
}
▶ Run

问题场景

rust
// 问题:表示方向
// 方案 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;  // 类型安全,有补全
▶ Run

枚举的优势

┌─────────────────────────────────────────────────────┐
│              枚举的优势                              │
├─────────────────────────────────────────────────────┤
│                                                     │
│  1. 类型安全                                         │
│     • 只能是定义的几个值之一                         │
│     • 编译器检查,防止无效值                         │
│                                                     │
│  2. 表达力强                                         │
│     • 每个变体可以携带不同数据                       │
│     • 可以精确描述状态                               │
│                                                     │
│  3. 穷尽检查                                         │
│     • match 必须处理所有情况                         │
│     • 添加新变体时,编译器提示更新代码               │
│                                                     │
│  4. 零成本抽象                                       │
│     • 和普通整数一样高效                             │
│     • 没有运行时开销                                 │
│                                                     │
└─────────────────────────────────────────────────────┘

定义和创建枚举

基本语法

rust
// 定义枚举
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!("向西"),
    }
}
▶ Run

枚举的内存表示

enum Direction {
    North,  // 0
    South,  // 1
    East,   // 2
    West,   // 3
}

内存布局:
┌─────┐
│  0  │  ← 用一个整数表示
└─────┘

大小:1 字节(可以用 u8 存储 4 个值)

带数据的枚举变体

rust
enum 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);

    // 每个变体可以携带不同类型和大小的数据
}
▶ Run

带数据枚举的内存布局

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 必须穷尽所有变体,保证安全

练习题

详见:练习题