Rust 是一门强调安全、并发、高效的系统编程语言。无 GC 实现内存安全机制、无数据竞争的并发机制、无运行时开销的抽象机制,是 Rust 独特的优越特性。 它声称解决了传统 C 语言和 C++语言几十年来饱受责难的内存安全问题,同时还保持了很高的运行效率、很深的底层控制、很广的应用范围, 在系统编程领域具有强劲的竞争力和广阔的应用前景。
在 Rust 笔记(三)中,讲了复核类型,本文就认识一下 Rust 中的变量。
Rust 默认支持类型推导,在编译器能够推导类型的情况下,变量类型一般可以省略,但常量(const)和静态变量(static)必须声明类型。
图片
let a: &str = "一个不可变变量";
const B: &str = "一个常量";
static C: &str = "一个静态变量";
变量默认是不可变的。如果需要让变量具有可变性,必须为变量添加 mut 关键字。默认变量不可变是一个很重要的特性,它符合最小权限原则(Principle of Least Privilege),有助于我们写出健壮且正确的代码。当你使用 mut 却没有修改变量,Rust 编译期会友好地报警,提示你移除不必要的 mut。
let mut x = 10; // 声明一个可变的整型变量
x = 20; // 可以修改 x 的值
当使用 mut 关键字声明一个引用时,该引用就可以被修改所指向的变量,例如:
let mut s = String::from("hello");
let r = &mut s; // 声明一个可变的字符串引用
r.push_str(" world!"); // 可以修改 s 的值
在其他大多数语言中,要么只支持申明可变的变量,要么只支持申明不可变的变量,但是 Rust 就不一样了,两者我都要,既要灵活性又要安全性。还有一个很大的优点,那就是运行性能上的提升,因为将本身无需改变的变量声明为不可变在运行期会避免一些多余的 runtime 检查。
选择可变还是不可变,更多的还是取决于你的使用场景,
在 Rust 中创建了一个变量却不在任何地方使用它,Rust 会给你一个警告,因为这可能会是个 BUG。
图片
但是有时创建一个不会被使用的变量是有用的,比如你正在设计原型或刚刚开始一个项目。这时你希望告诉 Rust 不要警告未使用的变量,为此可以用下划线作为变量名的开头:
图片
在其他语言中,比如 JS,我们使用 var a = "Hello World"。意思是将 "Hello World" 赋值给变量 a。在 Rust 中,let a = "Hello World",意思和 JS 中一样,但是这个过程起了有一个名字:变量绑定。
其实本质上是一回事,赋值 === 绑定,但是 Rust 存在“所有权”这一特性,所以绑定的含义更清晰准确。绑定就是把这个对象绑定给一个变量,让这个变量成为它的主人。
let 表达式不仅仅用于变量的绑定,还能进行复杂变量的解构:从一个相对复杂的变量中,匹配出该变量的一部分内容:
let (a, mut b): (bool, bool) = (true, false);
// a = true,不可变; b = false,可变
println!("a = {:?}, b = {:?}", a, b);
也可以进行变量的解构赋值:
let (a, b, c, d, e);
(a, b) = (1, 2);
Rust 允许对申明的变量再次声明,也就是允许申明相同的变量,后面的变量就会遮蔽前端的变量。
let x: i32 = 1;
let x: i32 = 2;
let x: i32 = x +1;
println!("x: {}", x);
这和 mut 变量的使用是不同的,第二个 let 生成了完全不同的新变量,两个变量只是恰好拥有同样的名称,涉及一次内存对象的再分配 ,而 mut 声明的变量,可以修改同一个内存地址上的值,并不会发生内存对象的再分配,性能要更好。
在命名方面,和其它语言没有区别,不过当给变量命名时,需要遵循 Rust 命名规范。详情可看RFC 430
有变量就有常量。常量也是绑定到一个常量名且不允许更改的值,但是常量和变量之间存在一些差异:
let a: &str = "一个不可变变量";
const B: &str = "一个常量";
常量可以在任意作用域内声明(包括全局作用域),在声明的作用域内,常量在运行的整个过程中都有效。对于需要在多处代码共享一个不可变的值时非常有用。