Rust基础-part3-函数
Rust基础[part3]_函数、流程控制
函数
组成和定义
fn add(i: i32, j: i32) -> i32 {i + j
}
- 声明函数的关键字
fn
- 函数名
add()
- 参数i和j和参数类型
i32
- 返回值类型`i32``
- 函数题
i+j
函数返回
返回形态
i+j
和 return i+j;
可以有两种形态
- return + 分号
- 无return + 无分号
无返回值的情况:
就返回 ()
fn add(i: i32, j: i32) -> () {}
永不返回值的情况:
!
表示函数永不返回,例如panic!
宏会导致程序崩溃,函数不会返回。
fn add_one(i: i32, j: i32) -> ! {panic!("weeee");
}
死循环也不会返回
fn infinite_loop() -> ! {loop {// 永远不会返回}
}
流程控制
if语法
// if_else();let number = 3;if number < 5 {println!("Condition was true");} else {println!("Condition was false");}// else iflet number = 3;if number % 4 == 0{println!("Condition was true");} else if number % 3 == 0 {println!("Condition was true for number % 3");} else if number % 2 == 0 {println!("Condition was true for number % 2");} else {println!("Condition was false");}
let 语句中使用if,需要注意分号结尾。
let condition = true;let number = if condition { 5 } else { 6 };println!("The value of number is: {}", number);
loop循环
//loop 循环loop {println!("This is an infinite loop");}
break、 continue
使用break 关键字来告诉程序停止循环,使用continue关键字来告诉程序继续循环。
let语句中也可以使用loop返回, 需要注意分号结尾。
// let语句中使用looplet result = loop {count += 1;if count == 10 {println!("Breaking the loop at count: {}", count);break count * 2; // 返回值}};
多层loop
break退出内层循环,可以使用命名loop的方法来退出指定的循环。标签的语法是使用单引号(')后跟一个标识符
// 多层循环可以使用标签来控制跳出特定的循环层级// 标签可以帮助我们在多层嵌套循环中跳出特定的循环层级// 标签的语法是使用单引号(')后跟一个标识符let mut i = 0;'outerloop: loop {loop {i += 1;println!("Inner loop iteration with i: {}", i);if i == 2 {println!("Breaking out of the inner loop at i: {}", i);break; // 跳出内层循环}if i == 3 {println!("Breaking out of the outer loop at i: {}", i);break 'outerloop; // 跳出外层循环}}}
while 条件循环
fn while_example() {let mut count: i32 = 0;while count < 5 {count += 1;println!("Current count: {}", count);}
}
在rust中如果是条件判断的循环,使用while是比较便捷的,如果需要遍历集合的话,可以使用for
for遍历集合
fn for_example() {let numbers = [1, 2, 3, 4, 5];for i in numbers {println!("Current number: {}", i)}// 直接遍历数值,逆序使用rev()for i in (1..=4).rev() {println!("Current number in range: {}", i);}
}
所有权转移与借用:
是Rust中的循环访问规则
1. 未实现Copy
trait的类型:所有权会转移(Move语义)
像Vec
这类集合类型没有实现Copy
trait,当直接用它们进行循环遍历(for v in vec
)时,循环会获取vec
的所有权(即“所有权转移”)。
- 循环结束后,
vec
的所有权已被消耗,无法再被访问(编译器会报错)。
let mut vec = vec![1, 2, 3, 4, 5];
// 直接遍历vec:所有权转移给循环变量v
for v in vec {println!("Current value: {}", v); // 此时v是vec中元素的所有权持有者
}// ❌ 错误:vec的所有权已转移,无法再使用
println!("Vector after loop: {:?}", vec);
2. 解决办法:用“借用”避免所有权转移
若想在循环后继续使用vec
,需通过引用(&) 进行“借用”,而非直接转移所有权。根据是否需要修改元素,分为两种借用方式:
(1)不可变借用(&vec
):仅读取,不修改
用&vec
进行遍历,循环获取的是vec
的不可变引用,所有权仍归原变量所有。
- 循环中只能读取元素,不能修改。
let vec = vec![1, 2, 3, 4, 5];
// 不可变借用:&vec表示“临时借用vec的读取权”
for v in &vec {println!("Current value: {}", v); // v是&i32类型(不可变引用)
}// ✅ 合法:vec所有权未转移,可继续使用
println!("Vector after loop: {:?}", vec);
(2)可变借用(&mut vec
):需要修改元素
若要在循环中修改元素,需用&mut vec
进行可变借用,此时循环变量v
是&mut i32
(可变引用)。
- 修改元素时需用
*v
解引用(获取引用指向的实际值)。
let mut vec = vec![1, 2, 3, 4, 5];
// 可变借用:&mut vec表示“临时借用vec的修改权”
for v in &mut vec {if *v == 3 {*v += 10; // ✅ 解引用后修改:3 → 13}println!("Current value: {}", v); // v是&mut i32,打印时自动解引用
}// ✅ 合法:所有权未转移,修改后的值已保留
println!("Vector after loop: {:?}", vec); // 输出 [1, 2, 13, 4, 5]
3. 实现Copy
trait的类型:所有权不转移(Copy语义)
像整数、布尔值等基本数据类型,以及由它们组成的数组([i32; n]
),都实现了Copy
trait。
- 循环遍历这类类型时,会自动复制元素(而非转移所有权),原变量的所有权仍保留,循环后可正常使用。
let arr = [1, 2, 3, 4, 5]; // 数组元素是i32(实现了Copy)
// 遍历arr:会复制每个元素给v,而非转移所有权
for v in arr {println!("Current value: {}", v); // v是复制的i32值
}// ✅ 合法:arr的所有权未转移,可继续使用
println!("Array after loop: {:?}", arr); // 输出 [1, 2, 3, 4, 5]
核心区别总结
类型特征 | 循环方式 | 所有权状态 | 循环后能否使用原变量 |
---|---|---|---|
未实现Copy (如Vec ) | for v in vec | 所有权转移给v | 不能(已被消耗) |
未实现Copy (如Vec ) | for v in &vec | 仅借出不可变引用 | 能(所有权仍保留) |
未实现Copy (如Vec ) | for v in &mut vec | 仅借出可变引用 | 能(所有权仍保留) |
实现Copy (如[i32; n] ) | for v in arr | 元素被复制,所有权不转移 | 能(原变量未被修改) |