【问题标题】:Cannot move out of borrowed context [duplicate]无法移出借来的上下文[重复]
【发布时间】:2019-02-25 08:28:05
【问题描述】:

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

struct X;

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

impl A {
    pub fn get_field(&self) -> Option<&X> {
        return self.field.map(|value| &*value);
    }
}
error[E0507]: cannot move out of borrowed content
 --> src/lib.rs:9:16
  |
9 |         return self.field.map(|value| &*value);
  |                ^^^^ cannot move out of borrowed content

error[E0597]: `*value` does not live long enough
 --> src/lib.rs:9:40
  |
9 |         return self.field.map(|value| &*value);
  |                                        ^^^^^-
  |                                        |    |
  |                                        |    borrowed value only lives until here
  |                                        borrowed value does not live long enough
  |
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 8:5...
 --> src/lib.rs:8:5
  |
8 | /     pub fn get_field(&self) -> Option<&X> {
9 | |         return self.field.map(|value| &*value);
10| |     }
  | |_____^

我真的不明白为什么这不起作用。

【问题讨论】:

  • self.field.as_ref().map(Box::as_ref);return self.field.as_ref().map(|value| value.as_ref());
  • 感谢@TimDiekmann,这是完美的

标签: rust


【解决方案1】:

我真的不明白为什么这不起作用。

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

在方法get_field 中,您获得了对结构的引用,但如果可能,您希望获得对内部X 的引用。

以上内容仅通过查看A的函数签名和结构体定义即可得出结论。

查看函数体,self.fieldOption&lt;_&gt; 类型,map 是它的方法。看the documentation for Option::map

pub fn map<U, F>(self, f: F) -> Option<U> 
where
  F: FnOnce(T) -> U,

通过将函数应用于包含的值,将 Option&lt;T&gt; 映射到 Option&lt;U&gt;

它接受一个只能运行一次的闭包,在你的情况下接受一个Box&lt;X&gt;,然后根据你的函数返回类型它应该返回&amp;X。乍一看,它看起来像是完美的匹配,因为 if value: Box&lt;X&gt; 然后 *value: X&amp;*value: &amp;X,但它无法编译!怎么了?

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

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

但是,您的get_field 方法不允许删除方法接收器self.fieldself 只是对A 的引用,所以self.field 也只是一个引用。然后你就不能调用map来消费self.field

解决办法,就是使用as_ref:

pub fn as_ref(&self) -> Option<&T>

Option&lt;T&gt; 转换为Option&lt;&amp;T&gt;

虽然它说从Option&lt;T&gt; 转换,但从签名中你可以看到它接受&amp;Option&lt;T&gt;,所以它只是将外部&amp; 移动到内部。现在你可以使用map

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

现在可以了。

【讨论】:

    猜你喜欢
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    • 2019-06-13
    • 2015-03-18
    • 1970-01-01
    相关资源
    最近更新 更多