【问题标题】:Why doesn't a trait object move when it calls enumerate()? [duplicate]为什么调用 enumerate() 时 trait 对象不移动? [重复]
【发布时间】:2021-12-19 05:17:49
【问题描述】:

我先给代码

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);
}

这是我运行此测试时的输出

运行 1 次测试

0 a

1 b

2 c

测试 test_trait ... 好的

为什么调用 enumerateiter 没有移动?

enumerate 接受 self 作为它的第一个参数,所以我认为它应该移动 iter, 但事实并非如此!第二个for循环仍然可以运行,没有任何编译错误。

【问题讨论】:

  • 让我理清思路。 &amp;mut dyn Iterator&lt;Item=String&gt; 以某种方式实现了Iterator&lt;Item=String&gt; 特征,所以iter 可以调用enumerate 函数,并且因为Self&amp;mut,所以iter 不会根据上面提到的答案移动。而且&amp;mut dyn Iterator&lt;Item=String&gt; 实现了IntoIterator,所以iter.into_iter() 在第二个for 循环中被调用。这次Self也是&amp;mut(我猜),为什么感动?
  • 这里是 explanation 为什么 iter 会被 for 循环移动。由于引用post中解释的重新借用,它不会被枚举移动。

标签: rust iterator move ownership trait-objects


【解决方案1】:

在这种情况下,Self 实际上是&amp;mut (dyn Iterator&lt;Item = String&gt;),使enumerate 调用返回Enumerate&lt;&amp;mut (dyn Iterator&lt;Item = String&gt;)&gt;。我不太熟悉 Rust 如何处理这种动态 trait 对象,但我猜想在枚举结束时丢弃的实际上是引用。

顺便说一句——如果你使用 VSCode 和 Rust 分析器扩展,你可以打开“Inlay Hints: Type Hints”选项来查看事物的类型。 Intellij Idea IDE 有一个类似的选项,我想不起来了。这样我就可以通过创建枚举变量来查看类型,这就是它所显示的:

let a: Enumerate<&mut (dyn Iterator<Item = String>)>

【讨论】:

  • 但是第二个循环确实移动了iter,因为如果我添加第三个循环for v in iter,编译器会告诉我它被移动了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-10
  • 2018-08-06
  • 1970-01-01
相关资源
最近更新 更多