我无法理解 Rust 的“范围”定义(Rust 编程语言,第 2 版 Klabnik & Nichols)

I can't understand the Rust "scope" definition (Rust Programming Language, 2nd Ed. Klabnik & Nichols)

提问人:mnemotronic 提问时间:11/5/2023 更新时间:11/5/2023 访问量:60

问:

我很难理解 Rust 如何定义“范围”。或者也许是没有淀粉出版社的书中对“范围”的定义(我实际上买了这本书)。

在第 62 页的顶部:

作用域是程序中项有效的范围。

在下一段中:

该变量从声明之时起一直有效,直到 当前作用域的末尾。

在我看来,“范围”的这个定义是递归的。

现在翻开“参考文献和借用”部分,第 72 页:

变量(参数)“s”有效的作用域与任何函数参数的作用域相同。

所以参数的范围就是参数的范围。这对我没有帮助。

现在是第 75 页的第 2 段:

...引用的作用域从引入它的位置开始,一直持续到上次使用该引用。

啊哈。因此,变量可能会在其“上下文”(函数)结束之前超出范围。

问题 1:函数中定义的变量与传递给该函数的参数的“范围”定义是否不同?

问题 2:引用的范围处理是否与其他变量不同?

Q3:当函数参数或函数中声明的变量在函数结束前超出范围时,变量的存储是否在此时释放?即在函数返回给调用方之前?

Rust 参数 参考 范围

评论


答:

3赞 Chayim Friedman 11/5/2023 #1

实际上有三个不同的范围。块的作用域、变量的作用域和引用的引用对象的作用域。

块(大括号、)创建作用域。此范围意味着在块内声明的变量(直接)将一直存在到其结束。函数也以相同的方式创建作用域。{ ... }

变量的作用域基本上是它的活度 - 它在哪里活。它通常是从它的声明到它被声明的块(或函数)的末尾。但是,变量可能会被移动或删除,然后其生命周期将在块之前或之后结束。它的范围是到此结束还是在区块的尽头(并且价值的活跃度更长/更短)取决于一个争论。

所以当书上说:

作用域是程序中项有效的范围。

这里的“范围”是指变量(项)的范围。

当它说:

该变量从声明之点到当前作用域结束都有效。

这里的“scope”是指的范围。

第三个范围是参考文献的范围,本书在第 75 页中提到了这一点。通常,引用的范围与它所引用的项目的范围相同,但由于非词汇生存期,它可能会在引用最后一次使用之后提前结束。当可以使用对同一项目的其他引用时,由于 Rust 的借用规则(共享 xor 可变),这会影响到。

关于您的问题:

对于函数中定义的变量与传递给该函数的参数,“范围”的定义是否不同?

两者都在函数的作用域内(如果变量未在内部块中声明)。但是,函数中定义的变量在参数之前被删除,因此我们可以说它们的范围提前结束。

引用的范围处理是否与其他变量不同?

不完全是,但它们在最后一次使用后被认为不再活着,而不是在它们的块结束时。这并非引用所独有,但是,对于任何没有滴胶的变量都是如此。

当函数参数或函数中声明的变量在函数结束前超出范围时,变量的存储是否在此时释放?即在函数返回给调用方之前?

这取决于您如何定义“释放的内存”。

Rust 唯一能做的保证是,从函数返回后,堆栈指针将与输入之前相同。通常,它只会在函数返回时减少,一次而不是多次执行并节省 CPU 时间。

Rust 做出的另一个保证是确定性调用。变量在其块作用域的末尾被调用,除非它是从中移动的。因此,变量拥有的资源(例如堆分配)会在那里释放。DropDrop

是否释放变量的堆栈内存取决于您如何定义它。有时,如果变量的生存期不重叠,编译器可以重用变量的堆栈内存。其他时候它不会,但在变量的作用域结束后不会使用它。

评论

1赞 flakes 11/5/2023
最近让我感到困惑的部分是理解这些与实现 Drop 特征的变量相关的定义。有些变量似乎先于其他变量退出范围,这有点令人困惑。您为“非词汇生存期”提供的链接有助于消除我的困惑。谢谢!
0赞 mnemotronic 11/6/2023
@chayimfriedman:在开始阅读RFC 2094之后,我发现我的困惑并不是唯一的。感谢您的提醒!