Rust基础-part3-函数

Rust基础[part3]_函数、流程控制

函数

组成和定义

rust 复制代码
fn add(i: i32, j: i32) -> i32 {
    i + j
}
  • 声明函数的关键字 fn
  • 函数名add()
  • 参数i和j和参数类型 i32
  • 返回值类型`i32``
  • 函数题i+j

函数返回

返回形态

i+jreturn i+j;

可以有两种形态

  • return + 分号
  • 无return + 无分号
无返回值的情况

就返回 ()

rust 复制代码
fn add(i: i32, j: i32) -> () {
  
}
永不返回值的情况:

!表示函数永不返回,例如panic!宏会导致程序崩溃,函数不会返回。

rust 复制代码
fn add_one(i: i32, j: i32) -> ! {
    panic!("weeee");
}

死循环也不会返回

rust 复制代码
fn infinite_loop() -> ! {
    loop {
        // 永远不会返回
    }
}

流程控制

if语法

rust 复制代码
   // if_else();
    let number = 3;
    if number < 5 {
        println!("Condition was true");
    } else {
        println!("Condition was false");
    }
	
		// else if
 		let 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,需要注意分号结尾。

rust 复制代码
 let condition = true;
    let number = if condition { 5 } else { 6 };
    println!("The value of number is: {}", number);

loop循环

rust 复制代码
//loop 循环
    loop {
        println!("This is an infinite loop");
    }
break、 continue

使用break 关键字来告诉程序停止循环,使用continue关键字来告诉程序继续循环。

let语句中也可以使用loop返回, 需要注意分号结尾。

rust 复制代码
 // let语句中使用loop
    let result = loop {
        count += 1;
        if count == 10 {
            println!("Breaking the loop at count: {}", count);
            break count * 2; // 返回值
        }
    };
多层loop

break退出内层循环,可以使用命名loop的方法来退出指定的循环。标签的语法是使用单引号(')后跟一个标识符

rust 复制代码
 // 多层循环可以使用标签来控制跳出特定的循环层级
    // 标签可以帮助我们在多层嵌套循环中跳出特定的循环层级
    // 标签的语法是使用单引号(')后跟一个标识符
    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 条件循环

rust 复制代码
fn while_example() {
    let mut count: i32 = 0;
    while count < 5 {
        count += 1;
        println!("Current count: {}", count);
    }
}

在rust中如果是条件判断的循环,使用while是比较便捷的,如果需要遍历集合的话,可以使用for

for遍历集合

rust 复制代码
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的所有权已被消耗,无法再被访问(编译器会报错)。
rust 复制代码
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不可变引用,所有权仍归原变量所有。

  • 循环中只能读取元素,不能修改。
rust 复制代码
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解引用(获取引用指向的实际值)。
rust 复制代码
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

  • 循环遍历这类类型时,会自动复制元素(而非转移所有权),原变量的所有权仍保留,循环后可正常使用。
rust 复制代码
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 元素被复制,所有权不转移 能(原变量未被修改)
相关推荐
Cyanto32 分钟前
Spring注解IoC与JUnit整合实战
java·开发语言·spring·mybatis
写不出来就跑路39 分钟前
WebClient与HTTPInterface远程调用对比
java·开发语言·后端·spring·springboot
悠哉清闲1 小时前
C++ MediaCodec H264解码
开发语言·c++
张人玉1 小时前
c#中Random类、DateTime类、String类
开发语言·c#
Jinkxs1 小时前
JavaScript性能优化实战技术
开发语言·javascript·性能优化
天上掉下来个程小白1 小时前
MybatisPlus-06.核心功能-自定义SQL
java·spring boot·后端·sql·微服务·mybatisplus
知了一笑2 小时前
独立开发第二周:构建、执行、规划
java·前端·后端
寻月隐君2 小时前
想用 Rust 开发游戏?这份超详细的入门教程请收好!
后端·rust·github
晴空月明2 小时前
分布式系统高可用性设计 - 缓存策略与数据同步机制
后端
ydm_ymz3 小时前
C语言初阶4-数组
c语言·开发语言