1
1
# Rust 的变量与类型
2
2
3
- !!! caution
4
-
5
- 本页尚未完工
6
-
7
3
## 变量声明
8
4
9
5
Rust 语言中通过 ` let ` 关键字来声明变量。Rust 是一门静态强类型语言,因此任何一个变量都有一个确定、不可变的类型。如果在声明同时初始化,则可以依靠编译器的类型推断来得到变量类型,不一定需要显式指定类型。
@@ -41,6 +37,8 @@ a = 2; // 变量 a 可变,OK
41
37
42
38
这种说法是不严格的,但是这样思考可以快速上手。
43
39
40
+ Rust 的这种设计看似奇怪,其实也有其用意。一般大部分变量的值实际上都不需要修改,默认不可变可以强制程序员思考变量是否需要修改,从而避免了一些潜在的错误。而在 C++ 中想达到相同的效果,则需要主动使用大量 ` const ` 关键字,其繁琐会让大部分程序员不愿意这么做。
41
+
44
42
!!! note "如何打印一个变量"
45
43
46
44
```rust
@@ -50,6 +48,43 @@ a = 2; // 变量 a 可变,OK
50
48
51
49
这里的 `println!` 是一个宏,但使用起来与函数很相似。
52
50
51
+ ### 常量
52
+
53
+ Rust 中的常量使用 ` const ` 关键字声明,常量的值必须在编译期间确定。常量的类型必须显式指定。
54
+
55
+ ``` rust
56
+ const SECONDS_PER_DAY : i32 = 24 * 60 * 60 ; // 常量的值必须在编译期间确定. 能够通过编译
57
+ // const B = 1; // 常量必须显式指定类型,编译无法通过
58
+ const c : i32 = 1 ; // 能够通过编译,但会被编译器警告,因为常量名的规范是 大写字母+下划线
59
+ ```
60
+
61
+ !!! note "与 C++ 的对照"
62
+
63
+ Rust 的 `const` 在定位上和 C++ 的 `constexpr` 基本是一致的。
64
+
65
+ C++ 中,一般把 `const` 与 `constexpr` 所定义的量都笼统地称为“常量”。但从 Rust 的视角看,只有编译期常量才是真正的“常量”,而 C++ 中用 `const` 声明的所谓“常量”在语义上只是一个“不可变量”(readonly,只读),其实反而更接近 变量 而不是 常量。
66
+
67
+ 也许可以这样理解:常量是一个「值」;而变量是一个「对象」、其值可能要在运行时才能确定,而这个变量是否可变则是另一个回事。
68
+
69
+ 例如,定义数组要求数组的长度必须是常量表达式。但 C++ 中 `const` 声明的所谓“常量”并不一定能满足这点;而 C++ 中的 `constexpr` 与 Rust 中的 `const` 则都能满足。
70
+
71
+ ### 变量遮蔽
72
+
73
+ 其英文为 ` shadowing ` ,可被译为“遮蔽”、“重影”,是 Rust 的一种特殊语法,允许在同一作用域中声明一个与之前变量同名的新变量,从而遮蔽之前的变量。
74
+
75
+ 这相当于把变量名绑定到了一个新的值上,而不是修改了原来的值。这种特性在一些场景下很有用,可以减少变量的数量、减轻给变量取名字的负担。
76
+
77
+ ``` rust
78
+ let spaces = " " ; // spaces 是一个字符串
79
+ let spaces = spaces . len (); // spaces 变成了一个数字
80
+
81
+ let mut spaces = " " ; // spaces 是一个字符串
82
+ // spaces = spaces.len(); // 编译无法通过,因为 spaces 已经是一个字符串,不能再赋值为数字,类型不匹配
83
+
84
+ let mut num = 1 ;
85
+ num *= 2 ; // OK
86
+ ```
87
+
53
88
## 变量类型
54
89
55
90
### 基本类型
@@ -149,7 +184,29 @@ let arr_long: [i32; 100] = [0; 100];
149
184
150
185
!!! note "与 C++ 的对照"
151
186
152
- Rust 的数组可以直接作为参数传递,这一点与 C/C++ 不同(C++ 中的 `std::tuple` 与 Rust 的数组更加类似)。与 C/C++ 类似的是,数组的长度都是不可变的,变长的线性容器在两门语言中分别叫做 `std::Vec` 和 `std::vector`。
187
+ Rust 的数组可以直接作为参数传递,这一点与 C/C++ 不同(C++ 中的 `std::tuple` 与 Rust 的数组更加类似)。这是因为 Rust 的数组是在栈上分配的。与 C/C++ 类似的是,数组的长度都是不可变的,变长的线性容器在两门语言中分别叫做 `std::Vec` 和 `std::vector`。
188
+
189
+ Rust 的下标访问自带越界检查。
190
+
191
+ 下面的代码将会在编译时报错:
192
+
193
+ ``` rust
194
+ let arr = [1 , 2 , 3 ];
195
+ let element = arr [3 ]; // 编译器报错:index out of bounds: the length is 3 but the index is 3
196
+ ```
197
+
198
+ 下面的代码能够通过编译,但当输入的下标超出数组长度时,程序会立即退出而不允许访问越界的内存:
199
+
200
+ ``` rust
201
+ use std :: io;
202
+
203
+ let arr = [1 , 2 , 3 ];
204
+ let mut index = String :: new ();
205
+ io :: stdin (). read_line (& mut index ). expect (" Failed to read line" ); // 若输入10...
206
+ let index : usize = index . trim (). parse (). expect (" Index must be a number" );
207
+ let element = arr [index ]; // ...程序产生运行时错误并退出
208
+ println! (" The value of element is: {}" , element ); // 该行不会被执行
209
+ ```
153
210
154
211
### 单元类型
155
212
0 commit comments