rust 展开选项类型出错:无法移出位于共享引用后面的`*foo`

2ic8powd  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(122)

如果我们有下面的代码:

struct Config {
    username: Option<String>,
    password: Option<String>,
}

fn some_fn(config: Config) {
    let foo: &Option<String> = &config.username;
    let bar: Option<&String> = config.username.as_ref();
    let name1 = foo.unwrap(); // error
    let name2 = bar.unwrap(); // no error
}

字符串
我有错误:

error[E0507]: cannot move out of `*foo` which is behind a shared reference
   --> src\main.rs:9:17
    |
9   |     let name1 = foo.unwrap();
    |                 ^^^^--------
    |                 |   |
    |                 |   `*foo` moved due to this method call
    |                 help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |                 move occurs because `*foo` has type `Option<String>`, which does not implement the `Copy` trait
    |
note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `*foo`


我看了一下unwrap方法,它是这样的:

pub const fn unwrap(self) -> T {
        match self {
            Some(val) => val,
            None => panic("called `Option::unwrap()` on a `None` value"),
        }
    }


实际上,我不知道“共享引用后面有东西”到底是什么意思。乍一看,我在想,unwrap需要一个self参数,但foo得到了一个&Option<String>类型,它是一个引用,所以错误是有道理的。但是如果我把bar的类型改为引用,就像这样:

let bar: &Option<&String> = &config.username.as_ref();
    let name2 = bar.unwrap(); // I thought this time there should be a error while still no error


所以回到问题上,关键的区别是&Option<String>&Option<&String>之间,我只是不知道错误是什么意思,“*foo由于这个方法调用而移动”,为什么*foo不能移动到unwrap
这个问题的真正原因是什么?

slhcrj9b

slhcrj9b1#

实际上,我不知道“共享引用后面有东西”到底是什么意思。
它位于&(共享引用)的内部/后面。
乍一看,我在想,unwrap需要一个self参数,但是foo得到了一个&Option类型,它是一个引用,所以错误是有道理的。
这正是问题的根源。unwrap通过值获取Option,你试图在引用上调用它,所以它试图在*foo上调用方法(为了获得拥有的值),这是无效的:String不是Copy,所以Option<String>也不是Copy,因此*foo需要移动值,并且不可能将值移出共享引用。
第二种情况有效,因为bar&Option<&T>,引用总是Copy,这也使得选项Copy有效,所以*bar有效。因此unwrap编译得很好。
您可以通过解引用来查看它,甚至不需要涉及unwrap

fn main() {
    let foo: &Option<String> = &None;
    let bar: &Option<&String> = &None;
    
    // *foo;  // cannot move out of `*foo` which is behind a shared reference
    *bar;
}

字符串

相关问题