我是Rust和系统编程的绝对初学者。 Rust中const
的文档说明了这一点:
常量适用于程序的整个生命周期。更具体地说,Rust中的常量在内存中没有固定地址。这是因为它们有效地内联到他们使用的每个地方。由于这个原因,对同一个常量的引用不一定保证引用相同的内存地址。
我在C ++中只遇到过inline functions
,但从来没有内联const类型。有人可以提供一个初学者友好的解释,如何工作?
另外,我对no fixed address in memory
感到困惑。这是否意味着每次我们使用const
类型时,堆栈中的值仅为此表达式分配,并且在表达式执行完毕后,它将被销毁< / em>的
答案 0 :(得分:6)
我只是遇到了C ++中的内联函数,但从未使用内联const类型。
Rust中与const
最接近的是C ++中的enum
。
有人可以提供有关其如何运作的初学者友好解释吗?
简单的初学者的解释是:它只是有效,不要担心细节的细节。
另外,我对内存中没有固定地址感到困惑。这是否意味着每次我们使用const类型时,堆栈中的值仅为此表达式分配,并且在表达式执行完后,它将被销毁?
是。也许。否。
这正是它在锡上所说的内容:无法保证。这使编译器可以最大限度地自由优化。
好吧,这一切都很好,但......真的发生了什么?
在实践中,有两种情况:
简单是什么意思?这得看情况。对于每个调用站点,编译器可以决定“是否足够简单”,这是接近内联的位置。
这是否意味着每次我们使用const类型时,堆栈中的值只为此表达式分配,并且在表达式执行完毕后,它将被销毁?
它不会被破坏。 const
变量不能具有实现Drop
的类型。当它不再使用时,该值只是忘记。如果曾经占用了堆栈中的内存,有时候这个内存会被覆盖。
答案 1 :(得分:2)
const N: i32 = 5
与使用类型安全的C或C ++中的#define N 5
类似。
当类型匹配时,您可以将其视为文本替换,即let foo = 32 + N;
在您的示例中等同于let foo = 32 + 5;
。
答案 2 :(得分:1)
const
蚂蚁的行为根本不像常规变量;当你定义一个它甚至没有自己的范围用于借用检查目的。
比较以下代码片段生成的MIR:
fn main() {
const N: i32 = 5;
}
和
fn main() {
let n: i32 = 5;
}
你会发现N
扩展为更像是函数而不是变量:
const main::N: i32 = {
let mut _0: i32; // return pointer
bb0: {
_0 = const 5i32; // scope 0 at <anon>:2:20: 2:21
return; // scope 0 at <anon>:2:5: 2:22
}
}
当在表达式中使用它时,它的值被放置在堆栈中以用于该表达式,并且之后会被忘记。
编辑:至少这是在MIR级别上发生的事情。我不是低级优化的专家,因此必须在LLVM甚至ASM中检查实际结果(是否实际使用堆栈内存)。请注意,这也适用于常规变量。