Rust 中的不可变变量和常量变量有什么区别?

What is the difference between immutable and const variables in Rust?

我了解到,如果变量未使用 mut 显式声明为可变的,它将变为不可变的(声明后无法更改)。那为什么我们在 Rust 中有 const 关键字呢?他们不一样吗?如果不是,它们有何不同?

const 用于包含所有内容的编译时常量。例如,您可以创建一个固定大小的数组,其大小为 const,但不能使用 let 绑定。当然,这也意味着与 const.

绑定相比,您可以将更多的东西放入 let 绑定中

const 不适用于变量;它用于可能不会存储在任何地方的常量值;它们实际上是文字值的别名。

Non-mut let 声明一个在运行时创建的实际变量,可以移动(并且不再可访问),甚至具有内部可变性(如果它包含 Cell 成员,例如)在某些情况下。

常量不能是shadowed:

let x = 10u32;
const Y:u32 = 20u32;

let x = 11u32;
//error: duplicate definition of value `Y` [E0428]
//const Y:u32 = 21u32;

println!("x={} Y={}",x,Y); //x=11 Y=20

const,在 Rust 中,是 constant 的缩写,与 compile-time evaluation 有关。它显示:

  • 声明常量时:const FOO: usize = 3;
  • 声明编译时可计算函数时:const fn foo() -> &'static str

这些类型的值可以用作通用参数:[u8; FOO]。目前这仅限于数组大小,但有讨论、计划并希望将来进一步扩展它。

相比之下,let 绑定大约是 运行 次计算值。

请注意,尽管使用 mut 因为可变性的概念是众所周知的,但 Rust 实际上就在于此。 &T&mut T 是关于别名,而不是可变性:

  • &T: 共享引用
  • &mut T:唯一参考

最值得注意的是,某些类型具有 内部可变性 并且可以通过 &T(共享引用)进行变异:CellRefCellMutex


注意:mutconst 与原始指针(*mut T*const T)的另一种用法在这里不讨论.

此外,我们无法使用 let 生成全局项,但可以使用 const。这是一个例子。

const LENGTH:usize = 4;

fn main() {
    let arr:[i32; LENGTH] = [10,20,30,40];

    for i in 0..LENGTH{
        println!("{}", arr[i])
    }
}

有关 conststaticlet 用法的更多信息: const and static

故事有点长。

一个const不代表一个内存位置而是一个值。 const 值在使用位置直接内联。在表达式计算期间创建的任何临时对象只能由编译器在编译时访问。可以在全球范围内。无法引用运行时项。必须有类型注释。

让值代表一个内存位置。 let 绑定的不变性是编译器强制执行的事情,可以使用 mut 修饰符进行更改。它是运行时构造。始终在本地范围内。它们的类型可以由编译器推断出来。

为了完整起见,static 也像 let 一样表示内存位置,但对同一静态的任何引用实际上是对同一内存位置的引用。静态就是静态。它们被编译成可执行文件,并且在 运行 程序的整个生命周期内都可以访问。可以在全球范围内。可以参考其他静力学。必须有类型注释。

从概念上讲,const 项目在解析之前被替换,类似于 C 宏所做的。这使得它可以在不允许使用普通变量的情况下使用。

const TEN: u32 = 10;
let ten = 10;

// OK
match x {
    TEN => do_a(),
    _ => do_b(),
}

// Nah...
match x {
    ten => do_a(),
    _ => do_b(),
}

// ...use this instead
match x {
    y if x == ten => do_a(),,
    _ => do_b(),
}