在Rust中,迭代器返回的是项目的引用还是值?

10

如果我有一个向量:

let mut v = vec![0, 1, 2, 3, 4, 5];

我会循环遍历它:
for &item in v.iter() {}

这里的&item是引用还是值?从&部分来看似乎是引用,但阅读详细信息后似乎显示它是一个值?

1个回答

17
迭代器在Rust中返回项的引用还是项的值取决于具体情况。你可以通过查找文档中的关联类型Iterator::Item来确定项的类型。例如,Vec::iter()的文档告诉你返回类型是std::slice::Iter。而Iter的文档则列出了该类型实现的特性列表,其中包括Iterator trait。如果你展开文档,就可以看到更多信息。
type Item = &'a T

这告诉你,由Vec<T>::iter()返回的迭代器的项类型为&T,即您获得对向量本身的项类型的引用。

在表示法中

for &item in v.iter() {}
for item in &v {{/* 这里的&可以理解为引用,表示对v进行遍历 */}}

for后面的部分是一个被匹配到迭代器中的模式。在第一次迭代中,&item会与&0进行匹配,所以item变成了0。你可以在任何Rust介绍中了解更多有关模式匹配的内容。

另一种遍历向量v的方法是写成:

for item in v {}

这将“消耗”向量,因此循环后无法再使用它。所有项目都从向量中移出并按值返回。这使用了为Vec 实现的IntoIterator特征,因此请查阅文档以查找其项目类型!
上面的第一个循环通常被编写为
for &item in &v {}

这里借用引用v,作为类型&Vec<i32>的参考,并在该引用上调用IntoIterator方法,该方法将返回与上述相同的Iter类型,因此它也会产生引用。


1
“&item与&0匹配,因此item变为0”这句话的意思是应用了Copy特质,因此只支持原始类型吗? - rsalmei
4
无论是在let语句、match语句还是传递函数参数时,只要给一个变量命名,都遵循同样的规则:如果该值的类型实现了Copy,则该值会被复制,否则它将被移动。在这种情况下,该值位于引用后面,因此它不能被移动,而且这仅适用于实现了Copy的类型。这些类型不一定是“原始”类型,因为您也可以为自定义类型实现Copy - Sven Marnach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接