Rust 学习笔记 - 变量与可变性
本文属于学习笔记,内容可能有误、可能不全面,仅代表个人在学习这一特性时的理解和总结
开始学习Rust。这是第一篇学习笔记,记录一些基础的概念。
1 Rust 变量与可变性
1.1 常量
Rust中的常量与其他语言类似,使用 const 声明,命名规范为所有字母大写,用下划线分割 。
常量声明时,必须指定类型,必须赋初值。并且初值只能是常量表达式,不能是函数的调用结果、或是运行过程中计算得到的值。
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
1.2 变量
Rust中的变量使用 let 声明,可以自动推导类别,也可以使用 : 指定类别。
变量又分为:可变变量和不可变变量,let 声明的默认是不可变变量,在变量前加上 mut 才是可变变量。
1.2.1 可变变量
可变变量的使用方法是符合在其他编程语言里使用习惯的写法,直接使用 = 进行赋值,变量的类型无法更改。
fn main() {
let mut x = 5;
x = 6; // 正确
x = "abc"; // 改变了类型,错误
}
1.2.2 不可变变量 & Shadow
顾名思义,不可变变量无法直接复制修改:
fn main() {
let x = 5;
x = 6; // 错误
}
error[E0384]: cannot assign twice to immutable variable `x`
--> test.rs:3:5
|
2 | let x = 5;
| -
| |
| first assignment to `x`
| help: consider making this binding mutable: `mut x`
3 | x = 6; // 错误
| ^^^^^ cannot assign twice to immutable variable
error: aborting due to 1 previous error; 2 warnings emitted
传统的方法在Rust里变得复杂了,说明Rust一定提出了一个更好的特性——Shadow
Rust允许使用 let 创建同名变量,例如:
fn main() {
let x = 5;
println!("The value of x is: {}", x);
let x = 6;
println!("The value of x is: {}", x);
let x = x * 2;
println!("The value of x is: {}", x);
let x = "hello";
println!("The value of x is: {}", x);
}
结果是:
The value of x is: 5
The value of x is: 6
The value of x is: 12
The value of x is: hello
并不像其他编程语言里,定义同名变量通常会报错。Rust直接使用后定义的变量覆盖之前定义的变量。因为这是重新定义变量,所以甚至可以改变变量的类型。
这个过程被取了一个好听的名字 Shadow,新变量像把旧变量罩住了、盖住了一样。
这个特性最好用的地方就在于可以改变变量的类型。
在其他语言中经常有以下情况,在类型转换前后需要定义两个不同名称的变量,实际上他们表达的含义是完全相同的。
int main() {
char score_str[] = "123";
int score = atoi(score_str);
}
使用 Rust 可以解决这个问题:
fn main() {
let score = "123";
let score: i32 = score.parse().unwrap();
}
即保证了变量的强类型安全性,又保留了使用的便捷性。很优雅。
还有一个情景 shadow 很好用。假如我在写一个很复杂的数学公式,公式的好几个部分都用到了同样的符号 a
fn main() {
let a = 3;
let b = a + 1 ...
// 此处省略一大堆内容
// 在里上面的a隔了好多行的地方,我又想定义一个变量a
// 我可以当作之前从来没有使用过那个变量a一样,直接定义一个新的a
let a = 4;
// 在后续的代码中,我也会很自然的认为a就是我最近定义的a = 4
// 而不会是之前的 a = 3
}
另外,shadow 可变变量会报 warning:
fn main() {
let mut score = "123";
let score: i32 = score.parse().unwrap();
println!("score: {}", score);
}
warning: variable does not need to be mutable
--> test.rs:2:9
|
2 | let mut score = "123";
| ----^^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
warning: 1 warning emitted
score: 123
因为这样写语法上没问题,但是这样就改变了使用 mut 的本意。
我的理解是:
- 如果需要使用的变量是传统意义的变量,也就是其他编程语言中最常用的变量,使用
let mut声明可变变量。 - 不可变变量的 shadow 就是用来解决无用中间变量过多的问题。生命周期短的变量,都可以使用不可变变量,因为他们通常不会被修改,并且影响的范围很小。解决了一个变量名焦虑的问题。