【问题标题】:Why does cloned() allow this function to compile为什么 cloned() 允许这个函数编译
【发布时间】:2015-07-04 23:02:16
【问题描述】:

我开始学习 Rust,并尝试实现一个函数来反转字符串向量。我找到了一个解决方案,但我不明白它为什么有效。

这行得通:

fn reverse_strings(strings:Vec<&str>) -> Vec<&str> {
  let actual: Vec<_> = strings.iter().cloned().rev().collect();
  return actual;
}

但事实并非如此。

fn reverse_strings(strings:Vec<&str>) -> Vec<&str> {
  let actual: Vec<_> = strings.iter().rev().collect(); // without clone
  return actual;
}

错误信息

src/main.rs:28:10: 28:16 error: mismatched types:
 expected `collections::vec::Vec<&str>`,
   found `collections::vec::Vec<&&str>`
(expected str,
    found &-ptr) [E0308]

谁能给我解释一下为什么?第二个函数会发生什么?谢谢!

【问题讨论】:

    标签: rust


    【解决方案1】:

    所以对.cloned() 的调用本质上就像在同一位置调用.map(|i| i.clone())(即您可以将前者替换为后者)。

    问题是,当您调用iter() 时,您正在迭代/操作对正在迭代的项目的引用。请注意,向量已经包含“引用”,特别是字符串切片。

    所以为了放大一点,让我们将cloned() 替换为我上面提到的等价的map(),出于教学目的,因为它们是等价的。这实际上是这样的:

    .map(|i: & &str| i.clone())
    

    所以请注意,这是对引用(切片)的引用,因为就像我说的,iter() 操作的是对项目的引用,而不是项目本身。因此,由于正在迭代的向量中的单个元素是 &amp;str 类型,那么我们实际上得到了它的 reference,即 &amp; &amp;str。通过在每个项目上调用clone(),我们从&amp; &amp;str 变为&amp;str,就像在&amp;i64 上调用.clone() 会导致i64

    因此,为了将所有内容组合在一起,iter() 会遍历元素的引用。因此,如果您从您构建的迭代器(您通过调用 iter() 构建的)产生的收集项中创建一个新向量,您将获得一个对引用的引用的向量,即:

    let actual: Vec<& &str> = strings.iter().rev().collect();
    

    所以首先要意识到这与你所说的函​​数返回的类型Vec&lt;&amp;str&gt; 相同。然而,更根本的是,这些引用的生命周期对于函数来说是本地的,因此即使您将返回类型更改为 Vec&lt;&amp; &amp;str&gt;,您也会收到生命周期错误。

    但是,您可以做的其他事情是使用into_iter() 方法。此方法实际上确实 迭代每个元素,而不是对其的引用。但是,这意味着元素是从原始迭代器/容器中移动的。这仅在您的情况下才有可能,因为您按值传递向量,因此您可以将元素移出它。

    fn reverse_strings(strings:Vec<&str>) -> Vec<&str> {
      let actual: Vec<_> = strings.into_iter().rev().collect();
      return actual;
    }
    

    playpen

    这可能比克隆更有意义,因为我们是按值传递向量,所以我们可以对元素做任何事情,包括将它们移动到不同的位置(在这种情况下是新的反向向量) . 而且即使我们不这样做,向量也会在该函数的末尾被丢弃,所以我们也可以这样做。如果我们不允许这样做(例如,如果我们通过引用传递向量,或者更有可能是切片而不是向量),则克隆会更合适。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-30
      • 2020-05-28
      • 1970-01-01
      相关资源
      最近更新 更多