所有权:每个内存对象都有一个主人变量。

变量绑定:将对象绑定给一个变量,先前的主人就失去所有权。

let s1 = String::from("hello"); // 变量绑定
let s2 = s1; // s1 对该字符串对象的所有权被绑定到 s2, s1 不再有效

关键字 mut:声明可变变量。

let mut x = 5;
x = 6; // 可变

变量未使用警告:如果有变量在声明后从未使用,编译器将发出 #[warn(unused_variables)] 警告。

fn main() {
	let x = 5; // 变量未使用警告
	println!("Hello");
}

禁用变量未使用警告:

  • 在变量名前使用下划线(如 let _x = 5)禁用对该变量的未使用警告。
  • 在文件头部使用 #![allow(unused)] 禁用对文件中所有变量的未使用警告。

同名变量遮蔽

  • 同一作用域内,后声明的变量将覆盖先声明的同名变量。
  • 子作用域的变量将暂时覆盖父作用域的同名变量。
  • 不同类型的变量也可以遮蔽,本质上,先后两个变量仅仅是命名相同。
// 变量遮蔽
fn main() {
	let x = 5;
	// x = 5
	let x = x + 1;
	// x 在 main 内遮蔽, x = 6
	{
		let x = x * 2;
		// x 在块内遮蔽, x = 12
	}
	// 块的遮蔽解除, x = 6
	
	// 不同类型的同名变量也可以遮蔽
	let spaces = "   ";
	let spaces = spaces.len();
}

数组:

// 创建一个 f32 数组
let forty_twos = [42.0, 42f32, 42.0_f32];
 
// 打印数组中第一个值, 并控制小数位数为 2
println!("{:.2}", forty_twos[0]);

序列:

for i in 1..5 { } // 右开: [1, 5)
for i in 1..=5 { } // 右闭: [1, 5]
for i in 'a'..='z' { } // 不止是数值: ['a', 'z']

语句与表达式:

fn add_with_extra(x: i32, y: i32) -> i32 {
    let x = x + 1; // 语句
    let y = y + 5; // 语句
    x + y // 表达式
}
fn main() {
    let x = 5u32;
	
    let y = { // 用一个块表达式为变量 y 赋值
        let x_sq = x * x;
        let x_cb = x_sq * x;
        x + x_sq + x_cb // 表达式的值
    };
	
    let z = {
        x * 2; // 分号让表达式变成了语句, 因此 z 不是 x*2, 而是 ()
    };
}

发散函数:返回类型为 ! 的函数。

fn dead_end() -> ! {
	panic!("你已经到了穷途末路,崩溃吧!");
}

👉 2 所有权