一个简单的例子:
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");
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,输出是:
test
use
drop
end
test
end
drop
Run Code Online (Sandbox Code Playgroud)
我理解在这种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")?
这在Rustnomicon中解释:
从Rust 1.0开始,drop flags实际上并没有秘密地隐藏在任何实现Drop的类型的隐藏字段中.
隐藏字段告诉当前值是否已被删除,如果没有,则表示当前值是否已被删除.因此,这在运行时是已知的,并且需要一些簿记.
展望未来,有一个RFC可以删除这些隐藏的字段.
RFC的想法是通过以下方式替换隐藏字段:
这个新策略比旧策略有几个优点:
#[repr(C)]即使struct工具,现在总是会给出一个等同于C的表示Dropstruct大小)| 归档时间: |
|
| 查看次数: |
192 次 |
| 最近记录: |