Box

一、堆与栈的对比

  1. 栈内存连续分配,从高位地址向下增长,大小有限(主线程 8MB,普通线程 2MB) • 高效分配/释放:函数调用时自动管理临时栈,所有权转移时栈数据浅拷贝 • 适合小型数据(寄存器/缓存友好)

  2. 堆内存非连续分配,从低位地址向上增长,大小受物理内存限制 • 所有权明确:堆数据通过栈上的智能指针(如 Box<T>)管理 • 适合大型数据:避免深拷贝,所有权转移仅复制指针


二、Box<T> 的核心作用

将数据存储在堆上,栈中保留智能指针。零额外性能开销,仅需堆分配成本。


三、使用场景

  1. 显式堆分配

    let a = Box::new(3); // 堆上存储 3,a 为栈上的智能指针
    println!("{}", *a);  // 显式解引用
    
  2. 避免大数据的深拷贝

    let arr = Box::new([0; 1000]); 
    let arr1 = arr; // 仅复制指针,堆数据未拷贝
    
  3. 解决动态大小类型(DST)问题递归类型:通过 Box 固定大小

    enum List {
        Cons(i32, Box<List>), // 递归成员用 Box 包装
        Nil,
    }
    
  4. 特征对象(Trait Object)

    let elems: Vec<Box<dyn Draw>> = vec![Box::new(Button), Box::new(Select)];
    // 存储不同类型,统一为 `dyn Draw` 特征对象
    

四、内存布局

  1. 普通 Vec<i32> • 栈指针 → 堆上的连续数组

  2. Vec<Box<i32>> • 栈指针 → 堆上的 Box 指针数组 → 每个 Box 指向堆上的实际值

    let sum = **arr[0] + **arr[1]; // 双重解引用获取值
    

五、Box::leak 方法

作用:消费 Box 并泄漏内存,强制值拥有 'static 生命周期 • 场景:运行时初始化但需全局有效的数据(如配置)

let s = Box::leak(String::new().into_boxed_str());
// s: &'static str

六、注意事项

  1. 显式解引用:表达式不会隐式解引用,需用 ***
  2. 自动释放Box 离开作用域时自动调用 Drop 释放堆内存
  3. 性能权衡:堆分配适合大型数据,小型数据优先用栈

总结

Box<T> 是 Rust 中最基础的智能指针,用于堆分配、解决所有权转移效率问题、处理递归类型和特征对象。理解其内存布局及适用场景,能有效平衡性能与代码复杂度。

© 2025 All rights reservedBuilt with Flowershow Cloud

Built with LogoFlowershow Cloud