一个简单的例子:
struct A;
fn main() {
test(2);
test(1);
}
fn test(i: i32) {
println!("test");
let a = A;
if i == 2 {
us(a);
}
println!("end");
}
impl Drop for A {
fn drop(&mut self) {
println!("drop");
}
}
#[allow(unused_variables)]
fn us(a: A){
println!("use");
}
当我运行它时,输出是:
test
use
drop
end
test
end
drop
我理解在test(2)
案例中,a
移动到us(a)
,因此它的输出是" test-use-drop-end"
但是,在test(1)
中,输出是" test-end-drop",这意味着编译器知道a
未被移动。
如果调用了us(a)
,则无需将a
放入test(i)
,它将被删除us(a)
;如果未调用us(a)
,则必须在a
之后删除println!("end")
。
由于编译器无法知道是否调用了us(a)
,编译器如何知道a.drop()
之后是否应该调用println!("end")
?
答案 0 :(得分:9)
从Rust 1.0开始,drop flags实际上并没有秘密地隐藏在任何实现Drop的类型的隐藏字段中。
隐藏字段告诉当前值是否已被删除,如果没有,则表示当前值是否已被删除。因此,这在运行时是已知的,并且需要一些簿记。
展望未来,有一个到remove these hidden fields的RFC。
RFC的想法是用以下方法替换隐藏字段:
这种新策略比旧策略有几个优点:
#[repr(C)]
实现struct
Drop
现在也会始终提供与C相同的表示形式
struct
大小)