日子长到一天接一天,他们丧失了各自的名称。对于我来说,唯一还有点意义的词是“昨天”和“明天”。 ——《局外人》
Rust与其他语言与众不同的一点就是“不可变性”,对于大部分变量来说,可变性都不是他们的默认状态。但是对于一门编程语言来说,可变性又是必需的,所以Rust对此引入了mut关键词来修饰变量来使得变量是可变的——当一个绑定是可变的,这意味着你可以改变它指向的内容。先看一个小例子:
let mut num:i32 = 0;
let mut x:i32 = 9;
let borrow = &mut x;//等同于let borrow:&mut i32 = &mut x;
*borrow = 10;//位置2
borrow = &mut num;//位置1 error cannot assign to a immutable variable
这个例子定义了一个可变的32位长整数x,一个不可变绑定的引用——它指向一个可变的32位长整数。这意味着borrow不能够绑定到另外一个变量,如位置1所示。但是由于引用指向的是一个可变的数据,所以我们可以改变其指向的数据的值,就像位置2处的操作一样。
再看一个例子:
fn main(){
let mut num2:i32 = 3;
let mut num:i32 = 9;
{
let mut immutable_borrow:&mut i32 = &mut num;
*immutable_borrow = 10;
immutable_borrow = &mut num2;
println!("{}", *immutable_borrow);//3
}
println!("{}", num);//10
}
结构体字段级别可变性
可变性是借用或者绑定的属性之一,这意味着,在某些情况下我们不能够如愿所偿的使用mut关键字来修饰变量使得其可变。举个例子:在结构体之中,我们就不能够对一个普通数据类型的字段设置其为可变。如下所示:
struct Foo{
//error: expected identifier, found keyword `mut`
mut a: i32
}
所以说你不能够在结构体中的普通数据类型的字段设置mut。但是呢尽管不能够设置,但是仍旧可以改变字段的值.....看下面这个例子:
fn main(){
let mut foo1:Foo = Foo{a: 8};
foo1.a = 9;
println!("{}", foo1.a);
let foo2:Foo = Foo{a: 1};
//foo2.a = 3; error: cannot assign to immutable field `foo2.a`
//println!("{}", foo2.a);
}
struct Foo{
a: i32
}
impl Foo{
fn get_a(&self) -> i32{self.a}
}
上面很奇怪,要知道我们Foo结构体中的字段a是不可变的,尽管foo1是可变绑定,但是为什么可以改变foo1的a属性的值呢?这难道不是两回事吗?目前为止并不明白,不过为了达到字段级别可变性这一目的,还是有其它方法的:
use std::cell::Cell;
fn main(){
let foo:Foo = Foo{a: Cell::new(9)};
foo.a.set(99);
println!("foo.a {:?}", foo.a);//foo.a Cell { value: 99 }
}
struct Foo{
a: Cell<i32>
}