[ Rust笔记 一] 基础-变量与类型

变量

1
2
3
4
5
6
let variable : i32 = 100;

fn main() {
let x = 5;
x = 10;
}

这段代码会报错,变量是只读的。mut关键字申明的变量才是可写的。

1
2
let mut x = 5; // mut x: i32
x = 10;

mut x是一个“模式”​,我们还可以用这种方式同时声明多个变量

1
2
let (mut a, mut b) = (1, 2);
let Point { x: ref a, y: ref b} = p;

Rust中,每个变量必须被合理初始化之后才能被使用。
编译器会帮我们做一个执行路径的静态分析,确保变量在使用前一定被初始化:

1
2
3
4
5
6
7
8
9
fn test(condition: bool) {
let x: i32; // 声明 x,不必使用 mut 修饰
if condition {
x = 1; // 初始化 x,不需要 x 是 mut 的,因为这是初始化,不是修改
println!("{}", x);
}
// 如果条件不满足,x 没有被初始化
// 但是没关系,只要这里不使用 x 就没事
}

变量遮蔽,这两个x代表的内存空间完全不同,类型也完全不同,它们实际上是两个不同的变量。
作用 1.在同一个函数内部把一个变量转换为另一个类型的变量,但又不想给它们起不同的名字
2. 在同一个函数内部,需要修改一个变量绑定的可变性

1
2
3
4
5
6
fn main() {
let x = "hello";
println!("x is {}", x);
let x = 5;
println!("x is {}", x);
}
1
2
3
4
5
6
7
8
9
10
11
// 注意:这段代码只是演示变量遮蔽功能,并不是Vec类型的最佳初始化方法
fn main() {
let mut v = Vec::new(); // v 必须是mut修饰,因为我们需要对它写入数据
v.push(1);
v.push(2);
v.push(3);
let v = v; // 从这里往下,v成了只读变量,可读写变量v已经被遮蔽,无法再访问
for i in &v {
println!("{}", i);
}
}

类型推导

1
2
3
4
5
6
7
8
9
10
11
fn main() {
// 没有明确标出变量的类型,但是通过字面量的后缀,
// 编译器知道elem的类型为u8
let elem = 5u8;
// 创建一个动态数组,数组内包含的是什么元素类型可以不写
let mut vec = Vec::new();
vec.push(elem);
// 到后面调用了push函数,通过elem变量的类型,
// 编译器可以推导出vec的实际类型是 Vec<u8>
println!("{:? }", vec);
}

类型别名

1
2
3
4
5
6
7
8
type Age = u32;
fn grow(age: Age, year: u32) -> Age {
age + year
}
fn main() {
let x : Age = 20;
println!("20 years later: {}", grow(x, 20));
}

使用Double的时候,就等同于(i32, Vec),可以简化代码。
type Double = (T, Vec); // 小括号包围的是一个 tuple,请参见后文中的复合数据类型

静态变量

static GLOBAL: i32 = 0;
占用的内存空间不会在程序执行期间回收
必须在声明的同时进行初始化
初始化必须是编译期可确定的常量
带有mut修饰的全局变量,在使用的时候必须使用unsafe关键字

    fn main() {
       //局部变量声明,可以留待后面初始化,只要保证使用前已经初始化即可
        let x;
        let y = 1_i32;
        x = 2_i32;
        println!("{} {}", x, y);
       //全局变量必须声明的时候初始化,因为全局变量可以写到函数外面,被任意一个函数使用
        static G1 : i32 = 3;
        println!("{}", G1);
       //可变全局变量无论读写都必须用 unsafe修饰
        static mut G2 : i32 = 4;
        unsafe {
            G2 = 5;
            println!("{}", G2);
        }
       //全局变量的内存不是分配在当前函数栈上,函数退出的时候,并不会销毁全局变量占用的内存空间,程序
       退出才会回收
    }

常量

const GLOBAL: i32 = 0;
不允许使用mut关键字修饰
一定要是一个编译期常量,不能是运行期的值

它与static变量的最大区别:编译器并不一定会给const常量分配内存空间,在编译过程中,它很可能会被内联优化。因此,用户千万不要用hack的方式,通过unsafe代码去修改常量的值,这么做是没有意义的。以const声明一个常量,也不具备类似let语句的模式匹配功能。