← 返回首页

FIELD NOTE / 2026-08-15

rust语法

rustlings智能指针之box

这个练习介绍的是用 Box 实现递归类型。

这个练习介绍的是用 Box 实现递归类型。

问题:递归类型大小无限

原来的定义是:

enum List {
    Cons(i32, List),
    Nil,
}

Cons 包含一个 List,而这个 List 又可以是 Cons,继续包含另一个 List

Cons(i32, Cons(i32, Cons(i32, ...)))

因此,Rust 无法在编译时确定 List 的大小。

解决方案:使用 Box

Box<T> 本身的大小是固定的,因为它只保存一个指向堆内存的指针。真正的数据存储在堆上。

修改为:

enum List {
    Cons(i32, Box<List>),
    Nil,
}

此时 List 的大小是可以确定的:

  • Nil 不包含数据
  • Cons 包含一个 i32 和一个固定大小的 Box<List>

完整实现

#[derive(PartialEq, Debug)]
enum List {
    Cons(i32, Box<List>),
    Nil,
}

fn create_empty_list() -> List {
    List::Nil
}

fn create_non_empty_list() -> List {
    List::Cons(1, Box::new(List::Nil))
}

fn main() {
    println!("This is an empty cons list: {:?}", create_empty_list());
    println!(
        "This is a non-empty cons list: {:?}",
        create_non_empty_list(),
    );
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_create_empty_list() {
        assert_eq!(create_empty_list(), List::Nil);
    }

    #[test]
    fn test_create_non_empty_list() {
        assert_ne!(create_empty_list(), create_non_empty_list());
    }
}

Cons 的含义

List::Cons(1, Box::new(List::Nil))

表示:

1 -> Nil

如果要创建更长的链表:

let list = List::Cons(
    1,
    Box::new(List::Cons(
        2,
        Box::new(List::Cons(
            3,
            Box::new(List::Nil),
        )),
    )),
);

它表示:

1 -> 2 -> 3 -> Nil

为什么使用 Box::new

Box::new(List::Nil) 会:

  1. 创建一个 List::Nil
  2. 将它放到堆上
  3. 返回一个 Box<List> 指针

所以 Cons 的第二个字段符合定义:

Cons(i32, Box<List>)

另外,#[derive(PartialEq, Debug)] 让这个枚举支持:

  • Debug:使用 {:?} 打印
  • PartialEq:使用 ==!= 比较

其中 Box<List> 也会自动比较它指向的 List 内容。