把一个值放到堆上,并由一个唯一所有者管理它。
1.1 Box<T>特点:
(1)堆分配
(2)唯一所有权
(3)单线程
1.2 自动解引用
Box<T>实现了Deref,支持自动解引用操作,比如 *y。
rust
let x = 5;
let y = Box::new(x);
assert_eq!(5, *y);
1.3 Box<T>用途:
1.3.1 无法确定大小的值(递归类型)
rust
#[derive(Debug)]
enum List{
Cons(i32, Box<List>),
Nil,
}
fn main() {
let list=List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
println!("{:?}", list);
}
1.3.2 运行时多态(trait object)
rust
trait MyPrint {
fn print(&self);
}
struct m1{}
impl MyPrint for m1{
fn print(&self){
println!("m1");
}
}
struct m2{}
impl MyPrint for m2{
fn print(&self){
println!("m2");
}
}
fn main() {
let ml:Vec<Box<dyn MyPrint>>=vec![Box::new(m1{}),Box::new(m2{})];
for i in ml{
i.print();
}
}
1.3.3 大对象移动
rust
// 定义一个大结构体,使用 Vec 存储数据以避免栈溢出
#[derive(Debug)]
struct BigData {
buffer: Vec<u8>, // 使用 Vec 在堆上存储数据
}
impl BigData {
fn new(size: usize) -> Self {
Self {
buffer: vec![0; size], // Vec 初始化直接在堆上分配
}
}
}
// 该函数获取 Box 的所有权
fn process_data(data: Box<BigData>) {
println!("数据处理中,缓冲区大小: {} bytes", data.buffer.len());
// 当函数结束时,data 离开作用域,Box 自动释放堆上的内存
}
fn main() {
// 1. 在堆上分配大对象
// Box::new 会将 BigData 移动到堆上,main 函数的栈上只保留一个指针
let my_data = Box::new(BigData::new(1024 * 1024)); // 1 MB
println!("准备移动大对象...");
// 2. 移动所有权
// 这里发生的是"移动"而非"拷贝"。
// 仅拷贝了栈上的指针(8字节),而不是拷贝 1MB 的数据。
// my_data 在此之后不再有效。
process_data(my_data);
// println!("{:?}", my_data.buffer.len()); // 编译错误!my_data 的所有权已移走
}