rust语言学习笔记Trait(七) IntoIterator(由集合创建迭代器)

IntoIterator 是 Rust 迭代器的‌入口 trait 。它的核心职责是将一个类型(如集合、数组等)转换为一个实现了 Iterator trait 的迭代器对象。

  • 任何实现了 IntoIterator 的类型都可以直接在 for 循环中使用‌。

1、核心定义

rust 复制代码
pub trait IntoIterator {
    /// 迭代器产生的元素类型
    type Item;
    
    /// 具体的迭代器类型,必须实现 Iterator<Item = Self::Item>
    type IntoIter: Iterator<Item = Self::Item>;
    
    /// 消耗 self,创建并返回迭代器
    fn into_iter(self) -> Self::IntoIter;
}
  • **Item**‌: 定义迭代过程中产生的每个元素的类型。
  • ‌**IntoIter**‌: 定义实际执行迭代逻辑的类型。
  • ‌**into_iter(self)**‌: 这是转换的核心。注意它接收 self(按值传递),这意味着调用该方法通常会消耗原始数据的所有权(或者借用,取决于具体实现)。

2、三种迭代模式的所有权

(1)消费所有权 (impl IntoIterator for Vec<T>)

for item in vecvec.into_iter()
rust 复制代码
let v1 = vec![1, 2, 3, 4];
for i in v1 {                  // 消费所有权
    println!("{}", i);
}
println!("{:?}", v1);          // ❌已被移动


let v2 = vec![1, 2, 3, 4];
for i in v2.into_iter() {      // 消费所有权
    println!("{}", i);
}
println!("{:?}", v2);          // ❌已被移动

(2)不可变借用 (impl<'a, T> IntoIterator for &'a Vec<T>)

for item in &vec(&vec).into_iter()
rust 复制代码
let v1 = vec![1, 2, 3, 4];
for i in &v1 {                   // 不可变借用
    println!("{}", i);
}
println!("{:?}", v1);            // ✅正常输出


let v2 = vec![1, 2, 3, 4];
for i in (&v2).into_iter() {     // 不可变借用
    println!("{}", i);
}
println!("{:?}", v2);            // ✅正常输出

(3)可变借用 (impl<'a, T> IntoIterator for &'a mut Vec<T>)

for item in &mut vec(&mut vec).into_iter()
rust 复制代码
let mut v1 = vec![1, 2, 3, 4];
for i in &mut v1 {                  // 可变借用
    *i += 2;
}
println!("{:?}", v1);               // 已被修改


let mut v2 = vec![1, 2, 3, 4];
for i in (&mut v2).into_iter() {    // 可变借用
    *i -= 2;
}
println!("{:?}", v2);                // 已被修改

3、函数参数约束 IntoIterator

  • 函数参数必须满足:任何可迭代内容
rust 复制代码
use std::fmt::{Debug, Display};

fn my_fn<I, T>(v: I)
where
    I: IntoIterator<Item=T>,   // 参数必须实现了 IntoIterator
    T: Display,                // 用于 print 输出
{
    for i in v {               // 遍历迭代器
        print!("{}  ", i);
    }
    println!("");
}

fn main() {
    my_fn(vec![1, 2, 3]);             // Vec<i32>
    my_fn([1, 2, 3, 4]);              // &[i32]
    my_fn((5..9));                    // range(i32)
    my_fn(["aaa", "bbb", "ccc"]);     // &[&str]
}

4、自定义类型实现 IntoIterator

rust 复制代码
#[derive(Debug)]
struct MyList<T>(Vec<T>);              // 自定义集合

// 实现消费所有权的 IntoIterator
impl<T> IntoIterator for MyList<T> {
    type Item = T;
    type IntoIter = std::vec::IntoIter<T>;
    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

// 实现不可变引用借用的 IntoIterator
impl<'a, T> IntoIterator for &'a MyList<T> {
    type Item = &'a T;
    type IntoIter = std::slice::Iter<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        self.0.iter()
    }
}

// 实现可变引用借用的 IntoIterator
impl<'a, T> IntoIterator for &'a mut MyList<T> {
    type Item = &'a mut T;
    type IntoIter = std::slice::IterMut<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        self.0.iter_mut()
    }
}

fn main() {
    // 消费所有权
    let list1 = MyList(vec![1, 2, 3]);
    for item in list1 {
        println!("{}", item);
    }

    // 不可变借用
    let list2 = MyList(vec![4, 5, 6]);
    for item in &list2 {
        println!("{}", item);
    }

    // 可变借用
    let mut list3 = MyList(vec![4, 5, 6]);
    for item in &mut list3 {
        *item += 10;
    }
    println!("{:?}", list3);
}
相关推荐
Rabitebla3 小时前
【Linux系统编程】 指令(二):一条路径是怎么定位到文件的
linux·c++·笔记·学习·算法
库玛西4 小时前
数据结构与算法之美:树、森林与二叉树全解析
c语言·数据结构·笔记·考研·算法·学习方法
小贺儿开发4 小时前
Unity 结合百度AI开放平台 手写文字识别
人工智能·科技·学习·unity·云服务·文字识别·手写文字
传奇开心果编程4 小时前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
Amos_Web4 小时前
Rspack 源码解析(十):Hash 与 Asset 生成
前端·rust·源码阅读
是隼人4 小时前
buuctf-pwn ciscn_2019_sw_1(32位只有一次格式化机会)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
柯南46684 小时前
【AI开发之Rust】第 12 课:并发模型与同步原语
rust·编程语言
传奇开心果编程4 小时前
【Jetpack Compose基础语法学与练】第9课 SideEffect副作用 + LaunchedEffect,处理异步任务和生命周期
android·学习·ui·kotlin·android jetpack
传奇开心果编程4 小时前
【ArkUI 练中学】第14课:应用性能优化实战
学习·ui·华为·harmonyos
PNP Robotics5 小时前
【PNP具身解读】GPT6 Astra:具身智能新范式,大模型 + Franka机器人快速落地验证一、GPT6 Astra 背后的布局、数据与具身方向
人工智能·学习·机器学习·机器人