循环
for循环
说明
for循环会消耗所有权
| 场景 | 行为 | 所有权 |
|---|---|---|
for item in collection |
调用 .into_iter() |
转移所有权(move) |
for item in &collection |
调用 .iter() |
不可变借用(&T) |
for item in &mut collection |
调用 .iter_mut() |
可变借用(&mut T) |
元素是 Copy 类型(如 i32) |
自动复制,原值仍可用 | 安全 |
元素是非 Copy 类型(如 String) |
所有权被移走 | 原值不可用 |
范围循环
fn main() {
// 0-10
for i in 0..=10 {
println!("{}", i)
}
}
fn main() {
// 0-9
for i in 0..10 {
println!("{}", i)
}
}
数组循环
实现copy类型
内部值如果实现copy trait,那么会copy,不会移动所有权
fn main() {
let s = [1,2,3,4];
for i in s {
println!("i: {i}");
}
println!("s: {:?}", s);
}
没有实现copy类型
String没有实现copy trait,for循环会获取所有权
fn main() {
let s = [String::from("1"),String::from("2"), String::from("3"), String::from("4")];
for i in s {
println!("i: {i}");
}
// println!("s: {:?}", s); 打印就会报错,所有权移动都被移动了
}
vec循环
内部也一样,非copy trait类型获取所有权
fn main() {
let s = vec![String::from("1"),String::from("2"), String::from("3"), String::from("4")];
for i in s {
println!("i: {i}");
}
// println!("s: {:?}", s);
}
切片循环
数组切片
fn main() {
let s = [String::from("1"),String::from("2"), String::from("3"), String::from("4")];
for i in &s {
println!("i: {i}");
}
println!("s: {:?}", s);
}
vec切片
fn main() {
let s = vec![String::from("1"),String::from("2"), String::from("3"), String::from("4")];
for i in &s {
println!("i: {i}");
}
println!("s: {:?}", s);
}
&str循环
fn main() {
let s = "hello你好";
for i in s.chars() {
println!("i: {i}");
}
println!("s: {:?}", s);
}
HashMap循环
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
// 遍历键值对(借用)
for (k, v) in &map {
println!("{}: {}", k, v);
}
}
continue
跳过本次循环
fn main() {
let s = [1,2,3,4];
for i in s {
if i == 3 {
continue;
}
println!("i: {i}");
}
println!("s: {:?}", s);
}
break
跳出整个循环
fn main() {
let s = [1,2,3,4];
for i in s {
if i == 3 {
break;
}
println!("i: {i}");
}
println!("s: {:?}", s);
}
语法糖
for循环的本质是loop的语法糖
for pattern in iterable {
body
}
let mut iter = IntoIterator::into_iter(iterable);
loop {
match iter.next() {
Some(pattern) => { body },
None => break,
}
}
结构
元组
fn main() {
let s = [(1,2), (3,4), (5, 6)];
for (a,b)in s {
println!("{}-{}", a, b);
}
}
结构体
for P{x: aa, y: bb } in s可以重命名字段
#[derive(Debug)]
struct P {
x: String,
y: String
}
fn main() {
let s = [
P {x: String::from("AA"), y: String::from("BB")},
P {x: String::from("CC"), y: String::from("DD")}
];
for P{x: c, y: z} in &s {
println!("{}-{}", c, z);
}
println!("{:?}", s)
}
enumerate
fn main() {
let v = vec!["a", "b", "c"];
for (i, val) in v.iter().enumerate() {
println!("{}: {}", i, val);
}
}
内部clone问题
确实需要一个独立的String副本,可以clone
| 对比项 | item.as_str() |
item.clone() |
|---|---|---|
| 是否获取所有权 | 否(只借用) | 是(复制一份新 String) |
| 内存分配 | 无(只是指针+长度) | 有(堆上分配新内存) |
| 性能 | ⚡ 极快(O(1)) | 🐢慢(O(n),需复制所有字符) |
| 原数据是否可用 | 是 | 是(但浪费资源) |
// 直接传递 &str
for item in &vec_of_strings {
// 非必要不要使用clone,
// process(item.clone());
// 零成本,不会获取所有权
process(item.as_str());
}
while条件循环
基本语法
- 每次迭代前先求值
condition,condition必须是bool类型(Rust 不允许隐式转换) - 如果为 true,执行循环体;否则退出
while condition {
// 循环体
}
案列
fn main() {
let mut n = 5;
while n > 0 {
println!("{}", n);
n -= 1;
}
}
continue
fn main() {
let mut a = 10;
while a < 20 {
if a == 16 {
a += 1;
continue;
}
a += 1;
}
println!("{}", a);
}
break
fn main() {
let mut a = 10;
while a < 20 {
if a == 16 {
break;
}
a += 1;
}
println!("{}", a);
}
while-let
结构枚举
let State::Running(n) = state会消耗所有权
fn main() {
enum State { Running(i32), Stopped }
// 设置可变
let mut state = State::Running(5);
while let State::Running(n) = state {
println!("Countdown: {}", n);
if n == 0 {
// 重新赋值
state = State::Stopped;
} else {
// 重新赋值
state = State::Running(n - 1);
}
}
}
错误写法
opt已经被消耗,并且没有新的复制到原有的opt,opt也不是可变的
fn main() {
let opt = Some(String::from("data"));
while let Some(s) = opt {
println!("{}", s);
}
}
添加ref
每次都获取字符串的引用,那么这个会变为
死循环
fn main() {
let opt = Some(String::from("data"));
while let Some(ref s) = opt {
println!("{}", s);
}
}
loop无限循环
只有loop可以接受返回值
fn main() {
let mut n = 0;
loop {
if n > 5 {
break
}
println!("{}", n);
n+=1;
}
println!("我出来了!");
}
label标签
任何循环前面加一个
'label_name:
break 'label_name: 跳出指定循环continue 'label_name: 跳到指定循环的下一轮
语法
'label: while condition { ... }
'label: for item in collection { ... }
'label: loop { ... }
案例
for循环label
fn main() {
'outer: for i in 0..3 {
println!("Outer: {}", i);
'inner: for j in 0..3 {
println!("Inner: {}", j);
if i == 1 && j == 1 {
break 'outer; // 直接跳出最外层 for 循环!
}
}
}
println!("Done");
}
while循环label
fn main() {
let mut x = 0;
'outer: while x < 3 {
println!("Outer: {}", x);
let mut y = 0;
while y < 3 {
println!(" Inner: {}", y);
if x == 1 && y == 1 {
break 'outer; // 跳出外层 while
}
y += 1;
}
x += 1;
}
println!("Done");
}
loop循环label
loop跳出for循环
fn main() {
let s = 'outer: loop {
'aaa: for x in 0..3 {
for y in 0..3 {
println!("({}, {})", x, y);
if x == 1 && y == 1 {
println!("Skipping (1,1), restarting outer loop");
// 最内存for循环跳过后继续执行
continue;
} else if x == 1 && y == 2 {
// 跳出两次for循环
break 'aaa;
}
}
}
break 222; // 防止无限循环
};
println!("{}", s);
}
直接跳出loop循环
内部多层for循环,直接跳出到loop循环
fn main() {
let s = 'outer: loop {
for x in 0..3 {
for y in 0..3 {
println!("({}, {})", x, y);
if x == 1 && y == 1 {
println!("Skipping (1,1), restarting outer loop");
continue;
} else if x == 1 && y == 2 {
// 立即退出'outer标记的循环, 将 111 作为整个 loop 表达式的值
break 'outer 111;
}
}
}
break 222; // 防止无限循环
};
println!("{}", s);
}
continue+label
跳过指定label的本次循环,进入下次循环
fn main() {
loop {
'aa: for i in 0..=3 {
for j in 0..=3 {
if i == 1 && j == 1 {
continue 'aa;
} else {
println!("i-{}, j-{}", i, j);
}
}
}
break;
};
}

浙公网安备 33010602011771号