You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中为什么trait对象调用enumerate()时未被转移所有权?

Rust 迭代器可变引用所有权问题解答

问题复现

你提供的代码如下:

fn dump(iter: &mut dyn Iterator<Item=String>) {
    for (i, v) in iter.enumerate() {
        println!("{} {}", i, v);
    }
    for v in iter {
        println!("{}", v);
    }
}

#[test]
fn test_trait() {
    let v = vec!["a".to_string(), "b".to_string(), "c".to_string()];
    let mut iter = v.into_iter();
    dump(&mut iter);
}

运行测试的输出为:

running 1 test
0 a
1 b
2 c
test test_trait ... ok

核心原因

该现象的本质是 Rust 标准库对迭代器做了泛型自动实现:所有实现了 Iterator trait 的类型,它的可变引用 &mut I 也会自动实现 Iterator trait,实现逻辑大致如下:

impl<'a, I: Iterator + ?Sized> Iterator for &'a mut I {
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item> {
        (**self).next()
    }
}

当你对 &mut dyn Iterator 类型的 iter 调用 enumerate() 时:

  • enumerate 要求按值传递 self 入参,这里实际被转移走的是 iter 这个可变引用的临时副本,不是原 iter 变量本身的所有权
  • 临时副本被 enumerate 生成的迭代器消费,整个过程不会影响原 iter 变量的所有权
  • 所以第一个循环结束后,原 iter 变量依然是可用状态,第二个 for 循环可以正常编译通过

补充说明

输出中第二个 for 循环没有打印任何内容,是因为第一个循环已经把迭代器内的所有元素全部遍历完了,第二个循环执行时迭代器已经是空状态,不会进入循环体。

内容的提问来源于stack exchange,提问作者shimoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 01:15:05