当某些控制路径删除某个值时,该点之后的所有控制路径都无法再次访问该变量。在下面的示例中,在 if 语句之后访问防护将是一个错误。尽管如此,Rust 实际上不会删除该值,直到它超出范围。为什么不呢?我想不出任何合法的理由让对象保持活动状态,而且它似乎可能会导致死锁(这就是我遇到这种行为的方式)。
use scopeguard; // 1.2.0
fn func(guard: impl std::fmt::Debug) {
if false {
drop(guard);
}
println!("guard is not yet dropped")
}
fn main() {
let guard = scopeguard::guard((), |_| println!("value dropped"));
func(guard);
}
我想不出任何合理的理由让该对象保持活动状态Rust 遵循一致的语义规范,其中删除取决于超出范围。虽然替代语义是可能的,并且可能是未来 Rust 版本的主题,但如何提前删除事物的确切规则可能会增加复杂性并导致混乱。例如,
return
语句就是一个例外,因为以下代码有效:
fn func(guard: impl std::fmt::Debug) {
if false {
drop(guard);
return;
}
println!("{guard:?} is not yet dropped") // ScopeGuard { value: () } is not yet dropped
}
这可能会导致死锁如果您的代码似乎特别容易出现死锁,它可能会受益于
重构。否则,只需在 drop
之后添加/移动
if
。