如何让堆上的boxed对象留存至程序执行结束?
问题
出于实验目的(想在堆上分配大量对象并测量其性能),编写了如下代码:
struct Foo { x: u32 } for i in 0..1000 { let b = Box::new(Foo {x: i as u32}); let p = b.deref(); println!("Pointer: {:p}", p); }
得到的输出为:
Pointer: 0x600000780000 Pointer: 0x600000780000 Pointer: 0x600000780000 Pointer: 0x600000780000 Pointer: 0x600000780000 ...
所有地址相同,说明对象刚分配就被销毁了,希望避免这种情况,让对象占用的内存不被立即释放。
解决方法
核心原因是每次循环里的Box变量b在当前循环迭代结束后就会被Rust的所有权系统自动销毁,对应的堆内存也会被释放,所以下一次循环会重新复用这块地址。要保留这些对象的内存,需要延长它们的生命周期:
- 使用容器存储所有
Box:创建一个Vec<Box<Foo>>,每次循环把新创建的Box推入这个容器中。容器会持有这些Box的所有权,只要容器不被销毁,里面的所有Box对应的堆内存就会一直被占用。
修改后的代码示例:
struct Foo { x: u32 } fn main() { // 创建一个Vec来保存所有堆分配的对象 let mut objects = Vec::new(); for i in 0..1000 { let b = Box::new(Foo { x: i as u32 }); // 打印当前Box的指针 println!("Pointer: {:p}", b); // 将Box存入Vec,延长其生命周期 objects.push(b); } // 此时所有对象都存在于Vec中,内存未被释放 // 可以在这里进行性能测量等操作 }
运行这段代码后,每个输出的指针都会不同,因为每个Box对应的堆内存都被容器保留,不会被立即释放。
如果只是想测试堆分配性能而不需要保留对象引用,也可以通过手动作用域延长变量生命周期,但使用容器是最符合Rust风格且稳妥的方式。
内容的提问来源于stack exchange,提问作者yegor256
相关产品推荐
相关产品推荐

