为什么 clone() 不允许这个动作?

Why doesn't clone() allow for this move?

我不明白为什么以下内容不起作用:

use std::collections::HashMap;

#[derive(Debug,Clone,PartialEq)]
struct Foo<'a> {
    contents: HashMap<&'a str, Foo<'a>>,
}

fn bar<'a>(val: Foo<'a>) -> Foo<'a> {
    *val.contents.get("bar").clone().unwrap()
}
error[E0507]: cannot move out of a shared reference
 --> src/lib.rs:9:5
  |
9 |     *val.contents.get("bar").clone().unwrap()
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `Foo<'_>`, which does not implement the `Copy` trait

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8ab3c7355903fc34751d5bd5360bb71a

我正在执行 .clone(),我认为这应该允许我 return 其所有权应该与输入值分离的结果值,但这似乎不是案例.

另一个奇怪的事情,它本身并不是一个障碍,但可能暗示了潜在的问题,是由于某种原因 .clone() return 是 &Foo,它令人惊讶,因为在其他情况下,我大多看到 .clone()&T -> T 开始。这就是 * 在那里的原因;没有它,这不会通过类型检查。我知道 Rust 有一些“神奇的”referencing/dereferencing 规则,但我不太明白这一点。

HashMap.get returns 一个 Option<&T>。克隆此选项会为您提供另一个 Option<&T>,引用相同的对象。

如果您想将 Option<&T> 转换为新的 Option<T>,其中 T 支持 Clone,您可以使用 .cloned()。也不再需要取消引用,因为您有 T 而不是 &T.

这意味着您的代码看起来像 this:

use std::collections::HashMap;

#[derive(Debug, Clone, PartialEq)]
struct Foo<'a> {
    contents: HashMap<&'a str, Foo<'a>>,
}

fn bar<'a>(val: Foo<'a>) -> Foo<'a> {
    val.contents.get("bar").cloned().unwrap()
}