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
做同样的事情,或者是不同的不知何故?
我不确定为什么 & 在 &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
),因为它会影响您可以对项目(即在您的循环中)执行的特定操作。