为什么 Rust 编译器会按照声明的相反顺序删除未使用的变量?

问题描述 投票:0回答:1

Rust 书 第 15 章第 3 节中提供了一个示例,以显示 Rust 何时对变量 c 和 d 运行 drop 函数。

struct CustomSmartPointer { data: String, } impl Drop for CustomSmartPointer { fn drop(&mut self) { println!("Dropping CustomSmartPointer with data `{}`!", self.data); } } fn main() { let c = CustomSmartPointer { data: String::from("my stuff"), }; let d = CustomSmartPointer { data: String::from("other stuff"), }; println!("CustomSmartPointers created."); }
输出为:

CustomSmartPointers created. Dropping CustomSmartPointer with data `other stuff`! Dropping CustomSmartPointer with data `my stuff`!
我的问题是为什么 rust 编译器会按这个顺序删除变量?鉴于变量没有被使用或引用,它们不应该在声明后立即删除,并按照声明的顺序删除吗?

我还尝试了使用另一个声明的变量的相同代码。

//snip let e = CustomSmartPointer { data: String::from("more stuff"), };
并且输出保持反转

CustomSmartPointers created. Dropping CustomSmartPointer with data `more stuff`! Dropping CustomSmartPointer with data `other stuff`! Dropping CustomSmartPointer with data `my stuff`!
虽然变量被删除的方式让人想起数据是如何从堆栈中压入和弹出的,但这应该是一个转移注意力的事情。

rust memory-management smart-pointers
1个回答
0
投票
鉴于变量未被使用或引用,不应该在声明后立即将其删除

不。这种行为将使

RAII 变得不可能。例如这个:

let mut lock: Mutex<i32> = Mutex::new(1); ... { let mut guard = lock.lock().unwrap(); *guard += 1; }
这里的

guard

不仅在内部保存数据,更重要的是它是一个在drop时解锁底层锁的结构。由于在范围末尾发生了 drop,我自动锁定了整个范围。我不必记住手动解锁锁。如果范围包含例如 ifs,这将非常容易出错。

并按照宣布的顺序被删除?

顺序是次要的,事实上任何顺序都可以。但必须做出一些选择,并且保持一致是有用的。所以这里只有两个自然的选择:与声明的顺序相同或相反。

相反的顺序更自然。例如回到带锁的例子。假设我们有两个:

{ let mut guard1 = lock1.lock().unwrap(); let mut guard2 = lock2.lock().unwrap(); // do something }
您真的希望 lock1 在 lock2 之前解锁吗?我想大多数人都不会。

© www.soinside.com 2019 - 2024. All rights reserved.