流程控制
此笔记记录于Rust Course,大多数为其中的摘要,少数为笔者自己的理解
if
rust
if condition == true {
// A...
} else {
// B...
}
if
语句块是表达式,这里我们使用if
表达式的返回值来给number
进行赋值:number
的值是5
- 用
if
来赋值时,要保证每个分支返回的类型一样(事实上,这种说法不完全准确,见这里),此处返回的5
和6
就是同一个类型,如果返回类型不一致就会报错
rust
fn main() {
let condition = true;
let number = if condition {
5
} else {
6
};
println!("The value of number is: {}", number);
}
else if
rust
fn main() {
let n = 6;
if n % 4 == 0 {
println!("number is divisible by 4");
} else if n % 3 == 0 {
println!("number is divisible by 3");
} else if n % 2 == 0 {
println!("number is divisible by 2");
} else {
println!("number is not divisible by 4, 3, or 2");
}
}
for
rust
fn main() {
for i in 1..=5 {
println!("{}", i);
}
}
注意,使用 for
时我们往往使用集合的引用形式,除非你不想在后面的代码中继续使用该集合(比如我们这里使用了 container
的引用)。如果不使用引用的话,所有权会被转移(move)到 for
语句块中,后面就无法再使用这个集合了):
rust
for item in &container {
// ...
}
对于实现了
copy
特征的数组(例如 [i32; 10] )而言,for item in arr
并不会把arr
的所有权转移,而是直接对其进行了拷贝,因此循环之后仍然可以使用arr
。
如果想在循环中,修改该元素,可以使用 mut
关键字:
rust
for item in &mut collection {
// ...
}
如果想在循环中获取元素的索引:
rust
fn main() {
let a = [4, 3, 2, 1];
// `.iter()` 方法把 `a` 数组变成一个迭代器
for (i, v) in a.iter().enumerate() {
println!("第{}个元素是{}", i + 1, v);
}
}
不想声明变量:
rust
for _ in 0..10 {
// ...
}
两种循环方式优劣对比:
rust
// 第一种
let collection = [1, 2, 3, 4, 5];
for i in 0..collection.len() {
let item = collection[i];
// ...
}
// 第二种
for item in collection {
}
第一种方式是循环索引,然后通过索引下标去访问集合,第二种方式是直接循环集合中的元素,优劣如下:
- 性能:第一种使用方式中
collection[index]
的索引访问,会因为边界检查(Bounds Checking)导致运行时的性能损耗 —— Rust 会检查并确认index
是否落在集合内,但是第二种直接迭代的方式就不会触发这种检查,因为编译器会在编译时就完成分析并证明这种访问是合法的 - 安全:第一种方式里对
collection
的索引访问是非连续的,存在一定可能性在两次访问之间,collection
发生了变化,导致脏数据产生。而第二种直接迭代的方式是连续访问,因此不存在这种风险( 由于所有权限制,在访问过程中,数据并不会发生变化)。
由于 for
循环无需任何条件限制,也不需要通过索引来访问,因此是最安全也是最常用的,通过与下面的 while
的对比,我们能看到为什么 for
会更加安全。
continue
rust
for i in 1..4 {
if i == 2 {
continue;
}
println!("{}", i);
}
break
rust
for i in 1..4 {
if i == 2 {
break;
}
println!("{}", i);
}
while
rust
fn main() {
let mut n = 0;
while n <= 5 {
println!("{}!", n);
n = n + 1;
}
println!("我出来了!");
}
用while
实现前面的for
:
rust
fn main() {
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("the value is: {}", a[index]);
index = index + 1;
}
}
for
并不会使用索引去访问数组,因此更安全也更简洁,同时避免 运行时的边界检查
,性能更高。
loop
rust
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {}", result);
}
- break 可以单独使用,也可以带一个返回值,有些类似
return
- loop 是一个表达式,因此可以返回一个值