`for i in &v` 和 `for i in v` 之间有区别吗?

use*_*783 2 for-loop reference rust

我目前正在阅读The Rust Programming Language 的第 8 章,其中包含以下代码:

let v = vec![100, 32, 57];
for i in &v {
    println!("{}", i);
}
Run Code Online (Sandbox Code Playgroud)

我不知道为什么&在是必要的for i in &v。我尝试删除它,代码仍然有效。请问for i in v做同样的事情,或者是不同的不知何故?

Mas*_*inn 5

我不确定为什么 & 在 &v 中的 i 中是必需的。我尝试删除它,代码仍然有效。for i in v 是做同样的事情,还是有什么不同?

它做一些稍微不同的事情(或者如果你愿意,它在不同的结构上做同样的事情)。问题是在第 8 章,您对这些概念的了解有点早,尤其是在不了解您使用其他编程语言的经验的情况下。

我强烈建议你继续阅读,要么你最终会发现(或者你自己理解,我不记得它是否明确),或者你可以稍后再回来。

如果它真的困扰你,这是我的解释:

与其他各种编程语言一样,Rust 的for循环适用于可以迭代的任意事物(有时称为“可迭代对象”)。在 Rust 中,这个概念由 表示IntoIterator,也就是“可以转换为迭代器的东西”。现在“变成”前缀是重要的,因为它一般是指消费转换(之后Into特质)。那是,

let a = thing();
let b = a.into_iter();
// println!("{:?}", a); // probably an error because the previous line "consumed" `a` unless it's trivial and copy
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好。在一种情况下 Rust 调用Vec::into_iter,而在另一种情况下它调用<&Vec>::into_iter. 对于许多方法,这没有区别,因为只有一种这样的方法存在。但是,这确实很重要IntoIterator,因为两者都存在

impl<T> IntoIterator for Vec<T> 
Run Code Online (Sandbox Code Playgroud)

impl<'a, T> IntoIterator for &'a Vec<T>
Run Code Online (Sandbox Code Playgroud)

为什么和有什么区别?好吧,上面我注意到它IntoIterator消耗了它的主题,所以第一个消耗了Vec而第二个只是……消耗了对 a 的引用Vec,它甚至不消耗,因为引用可以被复制。

因此,在最初的情况下,您可以Vec在迭代之后继续使用,但在您修改之后就不能使用了,因为该向量已被 for 循环消耗和销毁。你可以看到通过添加

println!("{:?}", v);
Run Code Online (Sandbox Code Playgroud)

在循环之后,第二个将拒绝 build

对此还有另一个后果,这在这里不太相关,但在其他情况下:如果我们更广泛地查看两个实现的声明,我们会得到:

impl<T> IntoIterator for Vec<T> 
Run Code Online (Sandbox Code Playgroud)

所述Item相关联的类型是不同的:在第一种情况下,因为矢量被消耗迭代获取到的实际的项目集合中包含的移动(和提供)。然而,在第二种情况下,由于向量没有被消耗,循环不能拥有这些物品:那是偷窃,而在 Rust 中,你只能从尸体上偷窃。所以它只能分发对项目的引用

这主要与非Copy类型相关(这里的情况不是整数Copy),因为它会影响您可以对项目(即在您的循环中)执行的特定操作。