当前位置: 首页 > java >正文

Rust基础-part3-函数

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

函数

组成和定义

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

函数返回

返回形态

i+jreturn 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(如Vecfor v in vec所有权转移给v不能(已被消耗)
未实现Copy(如Vecfor v in &vec仅借出不可变引用能(所有权仍保留)
未实现Copy(如Vecfor v in &mut vec仅借出可变引用能(所有权仍保留)
实现Copy(如[i32; n]for v in arr元素被复制,所有权不转移能(原变量未被修改)
http://www.xdnf.cn/news/15095.html

相关文章:

  • 【硬核】6节串联锂电池均衡系统仿真_组内双向cuk均衡_组间双向反激式变压器
  • Go 编译报错排查:vendor/golang.org/x/crypto/cryptobyte/asn1 no Go source files
  • Android原生TabLayout使用技巧
  • Telnet远程连接实验(Cisco)
  • jenkins部署springboot+Docker项目
  • 数据结构:栈、队列、链表
  • OpenCV实现感知哈希(Perceptual Hash)算法的类cv::img_hash::PHash
  • 亿级流量下的缓存架构设计:Redis+Caffeine多级缓存实战
  • C#中的设计模式:构建更加优雅的代码
  • 深入探究编程拷贝
  • 【Spring Boot】Spring Boot 4.0 的颠覆性AI特性全景解析,结合智能编码实战案例、底层架构革新及Prompt工程手册
  • Vue 表单开发优化实践:如何优雅地合并 `data()` 与 `resetForm()` 中的重复对象
  • 两台电脑通过网线直连形成局域网,共享一台wifi网络实现上网
  • 排序算法(一):冒泡排序
  • nginx 负载均衡配置(加解决重复登录问题)
  • 没有管理员权限,在服务器安装使用 Jupyter + R 内核
  • 【Linux仓库】命令行参数与环境变量【进程·伍】
  • 如何通过多点监控提升公网 IP 的稳定性和访问可用性
  • 全球化 2.0 | 印尼金融科技公司通过云轴科技ZStack实现VMware替代
  • 业务建模如何让金融数字化转型 “轻” 装上
  • rom定制系列------红米note10 5G版camellia原生安卓14批量线刷 miui安卓11修改型号root版
  • C语言:20250711笔记
  • 动态规划初步(完全背包)
  • T16IZ遥控器教程__遥控器与无人机对频
  • 线性回归原理推导与应用(十):逻辑回归多分类实战
  • 视频人脸处理——人脸面部动作提取
  • Spring Boot主从数据库完全教程 - 从零到精通
  • ubuntu22默认安装firefox使用snap安装还老打不开解决办法
  • Unity Demo——3D平台跳跃游戏笔记
  • IDE 关联 Git 操作