变量绑定
rust通过静态类型来提供类型安全。变量绑定可以通过在声明变量的时候通过类型注解来实现。然而,在大多数情况下,编译器可以通过上下文推断出变量的类型,这在很大程度上减轻了类型注解的负担。
在rust中一般通过let
关键字来实现变量的绑定。
fn main(){
let an_integer = 1u32;
let a_boolean = true;
let unit = ();
let copied_integer = an_integer;
println!("An integer: {:?}", copied_integer);
println!("A boolean: {:?}", a_boolean);
println!("Meet the unit value: {:?}", unit);
// 对于没有使用的变量绑定,编译器会给出警告
// 可以通过在变量前面增加下划线的方式屏蔽编译器的警告
let _unused__variable = 3u32;
}
可变绑定
在rust中变量的绑定默认是不可变的,如果要想获得可变的绑定,可以通过使用mut
关键字实现。
fn main(){
let _immutable_binding = 1;
let mut mutable_binding = 1;
println!("Before mutation: {}", mutable_binding);
// OK
mutable_binding += 1;
println!("After mutation: {}", mutable_binding);
// 对不可变绑定进行修改,编译器会报错
_immutable_binding += 1;
}
作用域和变量覆盖
rust中的变量绑定有一个作用域,被限定在一个block
语句块中。
一个block语句块,是一个用{}
包围的语句集合。当然,变量的覆盖也是允许的。
fn main(){
// 在main函数中的绑定
let long_lived_binding = 1;
// 这是一个block块作用域,范围比main函数的作用域要小
{
// 这个绑定只存在于这个块中
let short_lived_binding = 2;
println!("inner short: {}", short_lived_binding);
// 这个绑定覆盖了在main函数作用域范围中的绑定
let long_lived_binding = 5_f32;
println!("inner long:{}", long_lived_binding);
}
// block块结束
// 由于short_lived_binding已经不存在于当前的作用域中
// 所以编译器在这里会报错
println!("outer short: {}", short_lived_binding);
println!("outer long: {}", long_lived_binding);
// 这个绑定会覆盖前面的绑定
let long_lived_binding = 'a';
println!("outer long: {}", long_lived_binding);
}
变量声明
可以在变量绑定之前声明变量,然后在后续进行初始化。然而,这种形式很少使用,因为这个可能会导致使用未初始化的变量
fn main(){
// 声明一个变量绑定
let a_binding;
{
let x = 2;
// 对绑定进行初始化
a_binding = x * x;
}
println!("a binding: {}", a_binding);
let another_binding;
// 使用未初始化的变量会导致编译器错误
println!("another binding: {}", another_binding);
another_binding = 1;
println!("another binding: {}", another_binding);
}
编译器禁止使用未初始化的变量,因为这样会导致未定义的行为。
变量冻结
当数据以不可变的方式绑定到相同的变量时,它同时也被冻结了。
冻结的数据直到不可变绑定离开作用域才可以修改。
fn main(){
let mut _mutable_integer = 7i32;
{
let _mutable_integer = _mutable_integer;
// 不可变绑定不可以修改,编译器会报错
_mutable_integer = 50;
}
// 此时没有被冻结
_mutable_integer = 3;
}