无法移出借用的上下文

Max*_*Max -1 rust

我有一个非常简单的代码,无法编译:

struct X;

struct A {
    field: Option<Box<X>>,
}

impl A {
    pub fn get_field(&self) -> Option<&X> {
        return self.field.map(|value| &*value);
    }
}
Run Code Online (Sandbox Code Playgroud)
struct X;

struct A {
    field: Option<Box<X>>,
}

impl A {
    pub fn get_field(&self) -> Option<&X> {
        return self.field.map(|value| &*value);
    }
}
Run Code Online (Sandbox Code Playgroud)

我真的不明白为什么这行不通。

Ear*_*ine 6

我真的不明白为什么这行不通。

您的代码定义了一个结构A,该结构可能会或可能不会X在堆中(不在堆栈中)保存一个。

在该方法中get_field,已给您对struct的引用,但X如果可能的话,您希望获得对inner的引用。

以上只是通过查看的功能签名和struct定义得出的结论A

查看函数体,self.field类型为Option<_>map是其方法。查看有关以下内容的文档Option::map

pub fn map<U, F>(self, f: F) -> Option<U> 
where
  F: FnOnce(T) -> U,
Run Code Online (Sandbox Code Playgroud)

通过将函数应用于包含的值来映射Option<T>Option<U>

它接受只能运行一次的闭包,Box<X>在您的情况下接受a ,然后根据您的函数返回类型应返回&X。它看起来像一个完美的搭配乍一看,因为如果value: Box<X>*value: X&*value: &X,但不编译!怎么了?

如果您仔细查看签名,map就会发现它有两个参数,而不是一个。第一个参数是“方法接收器” self,其类型为Self

在Rust中,这意味着此调用将需要消耗方法接收器;调用后,用于调用该方法的对象将不再有效。

但是,您的get_field方法不允许删除方法接收方self.fieldself只是对它的引用A,所以self.field也只是对的引用。然后,您将无法打电话map消费self.field

解决方案是使用as_ref

pub fn as_ref(&self) -> Option<&T>
Run Code Online (Sandbox Code Playgroud)

从转换Option<T>Option<&T>

尽管它说从转换Option<T>,但是从签名中您可以看到它接受&Option<T>,因此它只是&向内移动。现在您可以使用了map

 pub fn get_field(&self) -> Option<&X> {
    return self.field.as_ref().map(|value| &*value);
 }
Run Code Online (Sandbox Code Playgroud)

现在可以了。