将向量传入“for"循环与对向量的引用是什么意思? [英] What does it mean to pass in a vector into a `for` loop versus a reference to a vector?
问题描述
我对 Rust for
循环的工作方式感到困惑.考虑以下几点:
I'm confused by how Rust for
loops work. Consider the following:
#![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
与对向量的引用是什么意思?为什么,当你传入一个引用时,你会得到对项目的引用,而当你传入一个实际的向量时,你会得到实际的项目?
What does it mean to pass in a vector into for
versus a reference to a vector? Why, when you pass in a reference, do you get a reference to the items and when you pass in an actual vector, you get the actual items?
推荐答案
for
循环的参数必须实现 IntoIterator
.如果您查看 Vec
的文档a>,你会看到这两个实现的IntoIterator
:
The argument to a for
loop must implement IntoIterator
. If you check out the docs for Vec
, you will see these two implementations of IntoIterator
:
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
的值,因为迭代器就是这样定义的.
You get references for &vec
and values for vec
because that's how the iterators are defined.
有时,您会看到这些更明确的形式:iter
或 into_iter
.同样的逻辑适用;参见 iter 和 into_iter 有什么区别?
Sometimes, you'll see these as the more explicit forms: iter
or into_iter
. The same logic applies; see What is the difference between iter and into_iter?
您会遇到另一种形式:&mut vec
和 iter_mut
.它们返回向量中元素的可变引用.
There's another form that you will encounter: &mut vec
and iter_mut
. These return mutable references to the elements in the vector.
至于为什么存在差异...
As to why the differences at all...
使用对向量的引用允许您在循环完成后访问向量.这编译:
Using a reference to the vector allows you to access the vector after the loop is done. This compiles:
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
无法产生不是引用的值.
Ownership-wise, you can't get a value from a reference unless you clone the value (assuming the type can even be cloned!). This means &vec
is unable to yield values that aren't references.
Vec
迭代器的实现者可以选择只产生引用,但是将元素的所有权转移给迭代器允许迭代器的消费者做更多的事情;从能力的角度来看,它是首选.
The implementer of Vec
's iterator could have chosen to only yield references, but transferring ownership of the elements to the iterator allows the iterator's consumer to do more things; from a capability perspective it's preferred.
另见:
这篇关于将向量传入“for"循环与对向量的引用是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!