循环

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;
    };
}
posted @ 2026-01-30 11:19  lxd670  阅读(4)  评论(0)    收藏  举报