一、变量声明
编程语言基本上都离不开变量的使用,Rust也不例外。Rust的变量遵循先声明后使用的原则,类型没有“默认构造函数”,变量没有“默认值”,变量如果没有显式赋值,它就没有被初始化,编译器禁止使用未经初始化的变量,因为这会产生未定义行为。
和许多现有的编程语言一样,Rust变量必须由数字、字母、下划线组成,且不能以数字开头。Rust里面的下划线是一个特殊的标识符,在编译器内部它是被特殊处理的。它跟其他标识符有许多重要区别,下划线表达的含义是“忽略这个变量绑定,后面不会再用到了”。
对于局部变量,最常见的声明语为:let var : i32 = 1;
Rust的变量声明语法有以下特点:
以下是简单的代码样例:
fn main() {
let a: i32 = 1;
println!("{}", a);
// 变量b未显示声明初始化,使用报错
// println!("{}", b);
let _ = "hello";
// _ 是特殊的变量,表示“忽略这个变量绑定,后面不会再用到了”
// println!("{}", _);
}
二、变量绑定
在Rust中,一般把声明的局部变量并初始化的语句称为“变量绑定”
Rust中声明变量缺省是“只读”的,不可变的。如果我们需要让变量是可写的,那么需要使用mut关键字进行修饰。
以下是简单代码样例:
fn main() {
let _immutable_binding = 1; // 默认变量绑定,不可变
let mut mutable_binding = 1; //使用mut修饰符,变量可变
println!("_immutable_binding: {}", _immutable_binding);
println!("Before mutation: {}", mutable_binding);
mutable_binding = 5; // 可变变量可以修改
// _immutable_binding = 3; // 默认变量只读,不可变
println!("After mutation: {}", mutable_binding);
}
三、变量作用域和遮蔽
变量绑定有一个作用域,它被限定只在一个代码块中。 代码块是一个被 {} 包围的语句集合。
Rust允许在同一个代码块中声明同样名字的变量。如果这样做,后面声明的变量会将前面声明的变量“遮蔽”起来,这就叫变量的遮蔽。
以下是简单的代码样例:
fn main() {
// 此绑定生存于 main 函数中
let long_lived_binding = 1;
// 这是一个代码块,比 main 函数拥有更小的作用域
{
// 此绑定只存在于本代码块
let short_lived_binding = 2;
println!("inner of short_lived_binding: {}", short_lived_binding);
let short_lived_binding = 'b';
println!(
"inner of short_lived_binding after rebind: {}",
short_lived_binding
);
// 此绑定遮蔽了外面的绑定的long_lived_binding
let long_lived_binding = 5_f32;
println!("inner of long_lived_binding: {}", long_lived_binding);
}
// 代码块结束,short_lived_binding变量作用域结束
// 报错!`short_lived_binding` 在此作用域上不存在
// println!("outer short: {}", short_lived_binding);
println!("outer of long_lived_binding: {}", long_lived_binding);
// 此绑定遮蔽了前面的long_lived_binding绑定
let long_lived_binding = 'a';
println!(
"outer of long_lived_binding after rebind : {}",
long_lived_binding
);
}
四、静态变量
Rust中可以用static关键字声明静态变量:static GLOBAL: i32 = 0;
与let语句一样,static语句同样也是一个模式匹配。与let语句不同的是,用static声明的变量的生命周期是整个程序,从启动到退出。static变量的生命周期永远是’static,它占用的内存空间也不会在执行过程中回收。这也是Rust中唯一的声明全局变量的方法。
为了保证内存安全,全局变量有以下限制:
以下是简单代码样例:
fn main() {
//局部变量声明,可以留待后面初始化,只要保证使用前已经初始化即可
let x: i32 = 2;
println!("x : {} ", x);
//全局变量必须声明的时候初始化,因为全局变量可以写到函数外面,被任意一个函数使用
static G1: i32 = 3;
println!("G1 : {}", G1);
//可变全局变量无论读写都必须用 unsafe修饰
static mut G2: i32 = 4;
unsafe {
G2 = 5;
println!("G2 : {}", G2);
}
// 未使用unsafe关键字引用可变全局变量,编译报错
/*{
G2 = 5;
println!("G2 : {}", G2);
}*/
//全局变量的内存不是分配在当前函数栈上,函数退出的时候,并不会销毁全局变量占用的内存空间,程序退出才会回收
}