rust语言学习笔记(指针一)Box<T>(堆分配,独占所有)

把一个值放到堆上,并由一个唯一所有者管理它。

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 的所有权已移走
}