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
(共享引用)进行变异:Cell
、RefCell
、 Mutex
等
注意:mut
和 const
与原始指针(*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])
}
}
有关 const、static 和 let 用法的更多信息:
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(),
}
我了解到,如果变量未使用 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
(共享引用)进行变异:Cell
、RefCell
、 Mutex
等
注意:mut
和 const
与原始指针(*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])
}
}
有关 const、static 和 let 用法的更多信息:
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(),
}