Rust中的Box<T>智能指针

tianyi Lv3

引言

rust中有许多智能智能,关于智能指针的定义: 智能指针(Smart Pointers) 是一类封装了资源管理逻辑的数据结构,它们不仅仅是指向内存地址的“指针”,还负责资源的生命周期管理、所有权转移、引用计数、惰性计算等功能。 常见的智能指针有:

  • Box:在堆上分配数据;
  • Rc:单线程下的引用计数;
  • Arc:多线程下的原子引用计数;
  • RefCell:运行时可变性(单线程);
  • Mutex / RwLock:用于线程安全的内部可变性
  • Cell:简单值类型的内部可变性(不返回引用)等等。
    今天我们来着重介绍一下 Box

Box

Box本质上就是一个拥有所有权的指针,指向堆上存储的值 T。

1
let b = Box::new(123);
  • 123 是分配在堆上的
  • b 是一个指向这个堆上数据的指针

使用场景

  • 特意的将数据分配在堆上
  • 数据较大时,又不想在转移所有权时进行数据拷贝
  • 类型的大小在编译期无法确定,但是我们又需要固定大小的类型时
  • 特征对象,用于说明对象实现了一个特征,而不是某个特定的类型

接下来,我们来详细说明
第一点,我们在日常实践中几乎很少遇到,意义不大,略过。

避免栈上的数据拷贝

当栈上的数据转移所有权时,实际上进行的时数据的拷贝,最终新旧数据拥有的是不同数据,只是值相同而已,因此所有权并未转移。

但是堆上则不同,堆上数据的所有权转移,实际上是复制指针,底层的数据并不会被拷贝,再将新的指针赋予新的变量,然后让拥有旧指针的变量失效,最终完成了所有权的转移。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fn main() {
// 在栈上创建一个长度为1000的数组
let arr = [0;1000];
// 将arr所有权转移arr1,由于 `arr` 分配在栈上,因此这里实际上是直接重新深拷贝了一份数据
let arr1 = arr;

// arr 和 arr1 都拥有各自的栈上数组,因此不会报错
println!("{:?}", arr.len());
println!("{:?}", arr1.len());

// 在堆上创建一个长度为1000的数组,然后使用一个智能指针指向它
let arr = Box::new([0;1000]);
// 将堆上数组的所有权转移给 arr1,由于数据在堆上,因此仅仅拷贝了智能指针的结构体,底层数据并没有被拷贝
// 所有权顺利转移给 arr1,arr 不再拥有所有权
let arr1 = arr;
println!("{:?}", arr1.len());
// 由于 arr 不再拥有底层数组的所有权,因此下面代码将报错
// println!("{:?}", arr.len());
}

将动态大小类型变为 Sized 固定大小类型

这一方面最常用的实践就是实现我们特殊的数据结构,比如我们的递归数据结构类型

1
2
3
4
5
6
7
8
enum List {
Cons(i32, Box<List>),
Nil,
}

use List::*;

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

特征对象

我们一般无法使两个不同类型的变量放入一个数组中,但是特征对象可以做到。
特征对象(Trait Object) 是一种通过接口(trait)而非具体类型访问值的机制Box 表示一个指向某个实现了 Trait 的类型的值的堆分配指针。它启用了 动态分发(dynamic dispatch),即运行时通过 vtable 决定调用哪个具体实现。

大概做法就是使不同的类型实现一个相同的特征接口(trait),达到将一个特征近似的看作我们自定义的类型,即特征对象,而实现了这个特征的结构体或者类型,都将属于我们特征对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
trait Animal {
fn speak(&self);
}

struct Dog;
impl Animal for Dog {
fn speak(&self) {
println!("Woof!");
}
}

struct Cat;
impl Animal for Cat {
fn speak(&self) {
println!("Meow!");
}
}

fn make_animal() -> Box<dyn Animal> {
Box::new(Dog)
}

fn main() {
let a: Box<dyn Animal> = make_animal();
a.speak(); // 输出 Woof!
}
  • Title: Rust中的Box<T>智能指针
  • Author: tianyi
  • Created at : 2025-08-06 20:02:08
  • Updated at : 2025-08-07 16:06:00
  • Link: https://github.com/ztygod/2025/08/06/Rust中的Box-T-智能指针/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
Rust中的Box<T>智能指针