【问题标题】:What does it mean to pass in a vector into a `for` loop versus a reference to a vector?将向量传入“for”循环而不是对向量的引用是什么意思?
【发布时间】:2017-03-27 00:44:20
【问题描述】:

我对 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-loop rust


【解决方案1】:

for 循环的参数必须实现 IntoIterator。如果你查看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>
}

您将获得&amp;vec 的引用和vec 的值,因为这是定义迭代器的方式。

有时,您会看到这些更明确的形式:iterinto_iter。同样的逻辑适用;见What is the difference between iter and into_iter?

您会遇到另一种形式:&amp;mut veciter_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

在所有权方面,除非克隆值(假设类型甚至可以被克隆!),否则无法从引用中获取值。这意味着&amp;vec 无法生成非引用的值。

Vec 的迭代器的实现者可以选择只产生引用,但是将元素的所有权转移给迭代器允许迭代器的消费者做更多的事情;从能力的角度来看,它是首选。

另见:

【讨论】:

  • 第三个也值得一提:impl&lt;'a, T&gt; IntoIterator for &amp;'a mut Vec&lt;T&gt;
  • @Alec 不是一个坏主意,虽然我有时会担心新手的头脑会超负荷 ;-)
猜你喜欢
  • 2016-02-20
  • 2015-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-11
  • 2018-12-05
  • 1970-01-01
相关资源
最近更新 更多