我对Rust for
循环的工作方式感到困惑。考虑以下:
#![feature(core_intrinsics)]
fn print_type_of<T>(_: T) {
println!("{}", unsafe { std::intrinsics::type_name::<T>() });
}
fn main() {
let nums = vec![1, 2, 3];
for num in &nums { print_type_of(num); }
for num in nums { print_type_of(num); }
}
它输出以下内容:
&i32
&i32
&i32
i32
i32
i32
将向量传递给
for
而不是对向量的引用意味着什么?为什么当您传递引用时,您获得对项目的引用,而当您传递实际向量时,您就获得了实际项目?
最佳答案
for
循环的参数必须实现 IntoIterator
。如果 checkout docs for Vec
,则会看到IntoIterator
的这两个implementations:
impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>
}
impl<'a, T> IntoIterator for &'a Vec<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>
}
您可以获得
&vec
的引用和vec
的值,因为这是定义迭代器的方式。有时,您会看到这些形式更明确:
iter
或 into_iter
。逻辑相同。见What is the difference between iter and into_iter?您还会遇到另一种形式:
&mut vec
和 iter_mut
。这些返回对向量中元素的可变引用。至于为什么根本不同...
使用对向量的引用可以使您在循环完成后访问向量。编译如下:
let v = vec![1, 2, 3];
for i in &v {}
for i in &v {}
这不是:
let v = vec![1, 2, 3];
for i in v {}
for i in v {}
error[E0382]: use of moved value: `v`
--> src/main.rs:4:14
|
3 | for i in v {}
| - value moved here
4 | for i in v {}
| ^ value used here after move
|
= note: move occurs because `v` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
在所有权方面,除非克隆值(假设甚至可以克隆类型!),否则无法从引用中获取值。这意味着
&vec
无法产生不是引用的值。Vec
的迭代器的实现者可以选择仅产生引用,但是将元素的所有权转让给迭代器可以使迭代器的使用者做更多的事情。从功能的角度来看,它是首选。也可以看看:
关于for-loop - 与引用向量相比,将向量传递到 `for`循环是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63508534/