[Rust] 变量的属性: 不可变(immutable), 可变(mutable), 重定义(shadowing), 常量(const), 静态(static)
变量的可变性
在 Rust 中, 变量可以具有下面的属性。
- immutable: 不可变变量
- mutable: 可变变量
- shadowing: 重定义(遮蔽)一个变量
- const: 常量
- static: 静态变量
不可变变量(immutable) vs 可变变量(mut)
Rust 的安全哲学要求变量默认是不可变的。
fn main() {
// 定义一个不可变的变量
let x = 5;
// 错误: cannot assign twice to immutable variable `x`
// x = 6;
// 定义一个可变的变量
let mut y = 5;
// 正确。可以改变!
y = y + 1;
println!("{}", x + y);
}
重定义(shadowing) vs 可变变量(mut)
重定义(遮蔽)特性是一个 Rust 特有的语言特性。
相对于可变变量,重定义(遮蔽)一个变量,可以改变原有变量的数据类型和可变性。
fn main() {
// 定义一个不可变的变量
let x = 5;
// 重定义变量 x。注意:变量类型和可变性都可以变。
// 变量 x 从整数数据类(i32)型变成了字符串数据类型(String)。
// 变量 x ,因为声明了 mut ,可变性也变成可变的。
let mut x: String = (x + 1).to_string();
// 正确。可以改变!
x = x + ":1";
println!("{}", x);
}
重定义特性的其它特点:
- 重定义特性可以作用于不可变变量
- 重定义特性可以作用于可变变量
- 重定义特性不可以作用于 static 变量
- 重定义特性不可以作用于 const 常量
常量(const)
常量的一个非常重要的特点是: 它的值会在编译时被 copy 到使用的地方。
注意:这种 copy 也会发生在外部包被编译的场合。因此,一定要确保你的常量不会在后续的开发中发生变化。
静态(static)
一个静态变量在应用中拥有唯一的内存地址。
大多数场合,静态变量会被定义为可变的。
在 Rust 的安全哲学中静态变量不是线程安全的,所以可变的静态变量在被读和写的场合,都需要标识 unsafe。
// 定义一个可变的静态变量
static mut LEVEL: i32 = 5;
// 定义一个不可变的静态变量
static CORRECT: i32 = 1;
fn main() {
// 错误: note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
LEVEL = LEVEL + 1;
// 错误: note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
println!("{}", LEVEL);
// 正确: 不可变的静态变量是线程安全的。
println!("{}", CORRECT);
// 读写静态变量都需要在unsafe中
unsafe {
// LEVEL = LEVEL + 1;
println!("{}", LEVEL);
}
}
静态(static) vs 常量(const)
那么,什么时候使用静态变量?什么时候使用常量呢?
- 数据占有内存比较大的场合,使用静态变量;
- 程序需要变量的地址属性的情况下,使用静态变量;
- 变量需要是可变的情况下,使用静态变量;
- 其它场合,推荐使用常量;