rust for循环里的所有权 - into_iter / iter / iter_mut

文章目录

  • [1 遍历对象实质为 .into_iter() 生成的迭代器](#1 遍历对象实质为 .into_iter() 生成的迭代器)
  • [2 避免转移 .iter() / .iter_mut()](#2 避免转移 .iter() / .iter_mut())
  • [3 for循环里自变量为什么不用加mut](#3 for循环里自变量为什么不用加mut)
rust 复制代码
// for循环语法糖
for loop_variable in iterator {
    code()
}
// 解糖
{
    let result = match IntoIterator::into_iter(iterator) {
        mut iter => loop {
            match iter.next() {
                None => break,
                Some(loop_variable) => { code(); },
            };
        },
    };
    result
}

1 遍历对象实质为 .into_iter() 生成的迭代器

fn into_iter(self) -> Self::IntoIter

(注意:这里的IntoIter是关联类型,自定义的类型别名)

遍历未实现Copy trait的对象将发生所有权转移

rust 复制代码
let a = vec![0, 1]; // Vec未实现Copy trait
for i in a {i;}
// a; // 去掉注释;报错,a所有权转移

2 避免转移 .iter() / .iter_mut()

fn iter(&self) -> Iter
fn iter_mut(&mut self) -> IterMut

1)

rust 复制代码
let a = vec![0, 1]; 
for i in a.iter() {i;}
a; 

实际上,for循环可以遍历所有实现IntoIterator trait的对象,而IntoIterator trait必须实现的方法就是into_iter();

Iter和IterMut也都实现了IntoIterator trait,所以可以理解为上述代码解糖后操作的对象是a.iter().into_iter(),而基本库里Iter对象into_iter()方法实现是这样的:

rust 复制代码
impl<I: Iterator> IntoIterator for I {
    type Item = I::Item;
    type IntoIter = I; // 类型IntoIter就是待实现对象的类型,这里也就是Iter

    #[inline]
    fn into_iter(self) -> I {
        self // 将iter()产生的Iter对象原封不动地返回,但之前对象的所有权已经转移
    }
}

.into_iter()a.iter()原封不动地返回,此时for循环遍历的对象实质就是a.iter(),而.iter()传递的是调用者的引用

2)

另一种写法就是直接遍历对象的引用

rust 复制代码
    let a = vec![0, 1]; 
    for i in &a {i;}
    a; 

不可变引用都实现了 Copy trait这里自然不存在所有权转移;

同时,【摘自文档 https://rustwiki.org/zh-CN/std/iter/index.html】如果集合类型 C 提供 iter(),则它通常还为 &C 实现 IntoIterator,而该实现只是调用 iter()。 同样,提供 iter_mut() 的集合 C 通常通过委派给 iter_mut() 来为 &mut C 实现 IntoIterator。

所以,这里实际上操作的对象还是a.iter()

p.s 方法的调用会自动解引用,故&a.iter()和a.iter()等价

3 for循环里自变量为什么不用加mut

从文章开头贴出的代码可以看到,解糖后的代码自变量loop_variable实际只是存在于单次循环中的一个临时变量,可以理解成每次循环都会完成一次let loop_variable = iter.next();的赋值操作, 所以,自变量无需mut也能发生变化;当然,添加了mut也不会报错,只是会多个警告提示。

相关推荐
不写八个7 分钟前
Python办公自动化教程(005):Word添加段落
开发语言·python·word
HEX9CF11 分钟前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
凌云行者23 分钟前
使用rust写一个Web服务器——单线程版本
服务器·前端·rust
赵荏苒36 分钟前
Python小白之Pandas1
开发语言·python
丶Darling.38 分钟前
代码随想录 | Day26 | 二叉树:二叉搜索树中的插入操作&&删除二叉搜索树中的节点&&修剪二叉搜索树
开发语言·数据结构·c++·笔记·学习·算法
人生の三重奏1 小时前
前端——js补充
开发语言·前端·javascript
计算机学姐1 小时前
基于SpringBoot+Vue的高校运动会管理系统
java·vue.js·spring boot·后端·mysql·intellij-idea·mybatis
平凡的小码农1 小时前
JAVA实现大写金额转小写金额
java·开发语言
yttandb1 小时前
重生到现代之从零开始的C语言生活》—— 内存的存储
c语言·开发语言·生活
我明天再来学Web渗透1 小时前
【hot100-java】【二叉树的层序遍历】
java·开发语言·数据库·sql·算法·排序算法