Rust中Box指向对象被移动后的Drop调用逻辑疑问
Rust中Box指向对象被移动后的Drop调用逻辑疑问
首先咱们先还原你的问题场景:你观察到这段代码里Drop只被调用了一次,想搞清楚背后的逻辑:
In the following code 'Drop' is being called only once:
#[derive(Default)] struct MyStruct { my_int: i32, my_vec: Vec<i32>, } impl Drop for MyStruct { fn drop(&mut self) { println!("Dropping MyStruct"); } } fn main() { { let my_box =std::boxed::Box::new(MyStruct::default()); { let my_ref = *my_box; } // DROP IS CALLED HERE } // NOTHING IS CALLED HERE }
你的疑问是:是编译器知道Box已经不指向任何东西了所以不调用Box的Drop,还是Box确实被调用了Drop,但它知道里面已经没有MyStruct了所以不触发对应的Drop?
接下来咱们拆解清楚背后的逻辑:
- 首先,当你执行
let my_ref = *my_box;这一行时,你是把Box包裹的MyStruct完整地移动出来了。这时候my_box就变成了一个“空箱子”——它不再拥有堆上的MyStruct实例,那个值的所有权完全转移给了my_ref。 - 当内部作用域结束时,
my_ref被销毁,所以会调用MyStruct的drop方法,这就是你看到打印输出的来源。 - 而当外部作用域结束时,
my_box这个Box实例本身确实会被销毁,它的drop方法也确实会被调用。但Box的drop逻辑很明确:它只会在自己还持有堆上值的所有权时,才会清理堆内存并触发内部值的drop。现在里面的内容已经被移走,Box就只是个空壳,所以它的drop执行时啥也不用做,自然不会有额外的打印。
这里核心是Rust的移动语义在起作用:一个值只能被一个所有者持有,当你把Box里的值移走后,Box就失去了对它的所有权,后续销毁Box时自然不需要再管这个值的生命周期——毕竟那个值已经被my_ref接手,并且已经被销毁过一次了,Rust绝对不会允许同一个值被drop两次。
备注:内容来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

