Rust 里的 Box 到底是什么
学 Rust 时,Box<T> 很容易被一句话带过:它可以把数据放到堆上。 这句话没错,但如果只记住这一句,后面看到 Box<dyn Trait>、Box<List>、Pin<Box<T>>、Box::leak 时,还是会觉得它像一个突然冒出来的语法补丁。 更好的理解方式是:Box<T> 不是“逃离所有权系统”的工具,而是 Rust 所有权系统里最基础的一种拥有型指针。它让一个值住在堆上,同时让所有权仍然清清楚楚地归某个变量管理。 先看 Box 解决了什么问题 普通变量通常可以这样理解: let n = 42; n 这个值本身就放在当前栈帧里。栈很快,进入函数时分配,函数返回时回收,生命周期也很清楚。 但有些场景光靠栈不够舒服: 一个类型递归地包含自己,编译器算不出它的大小。 你想把不同具体类型放进同一个集合,只要求它们实现同一个 trait。 一个值很大,你希望移动时只移动一个指针。 某些 API 需要一个固定地址的拥有型对象,比如配合 Pin 使用。 这时 Box<T> 就出现了。 let n = Box::new(42); 可以把它粗略想成这样: 栈上变量 n -> 保存一个指针 -> 指向堆上的 42 Box<T> 本身在栈上,里面保存指向堆数据的指针。真正的 T 在堆上。变量离开作用域时,Box<T> 会自动释放堆上的 T。 所以 Box<T> 同时有两个特点: 它是指针,可以间接访问堆上的值。 它拥有这个值,离开作用域时负责释放它。 这和 C 里的裸指针很不一样。你不用手写 free,也不能随便复制出多个拥有者。Rust 仍然会检查所有权、移动和借用。 最基本的用法:Box::new 创建一个 Box<T> 最常见的方式是 Box::new: fn main() { let name = Box::new(String::from("cloudside")); println!("{name}"); } 这里 String 这个值由 Box 放到堆上管理,name 是一个拥有它的 Box<String>。注意,String 自己内部还会管理一块字符串缓冲区;这里说的是 String 这个三字段结构本身的位置。 ...