我有一段非常简单的代码,我无法编译:
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| | }
| |_____^
我真的不明白为什么这行不通。
答案 0 :(得分:5)
我真的不明白为什么这行不通。
您的代码定义了一个结构A
,该结构可能会或可能不会在堆(而不是堆栈)中保存X
。
在方法get_field
中,您获得了对该结构的引用,但是,如果可能,您希望获得对内部X
的引用。
仅通过查看A
的函数签名和结构定义来得出以上结论。
查看函数体,self.field
的类型为Option<_>
,map
是其方法。查看the documentation for Option::map
:
pub fn map<U, F>(self, f: F) -> Option<U> where F: FnOnce(T) -> U,
通过将函数应用于包含的值,将
Option<T>
映射到Option<U>
。
它接受只能运行一次的闭包,在您的情况下接受Box<X>
,然后根据您的函数返回类型应返回&X
。乍看之下,这似乎是完美的匹配,因为如果value: Box<X>
然后*value: X
和&*value: &X
,但它不会编译!怎么了?
如果您仔细查看map
的签名,您会发现它有2个参数,而不是1个。第一个参数是“方法接收器” self
,其类型为Self
。
在Rust中,这意味着此调用将需要使用方法接收方;调用后,用于调用该方法的对象将不再有效。
但是,不允许您的get_field
方法删除方法接收者self.field
:self
仅是对A
的引用,因此self.field
也是仅供参考。然后,您将无法调用map
来消耗self.field
。
解决方案是使用as_ref
:
pub fn as_ref(&self) -> Option<&T>
从
Option<T>
转换为Option<&T>
。
尽管它说从Option<T>
进行转换,但是从签名中您可以看到它接受&Option<T>
,因此它只是将外部&
移入了内部。现在您可以使用map
。
pub fn get_field(&self) -> Option<&X> {
return self.field.as_ref().map(|value| &*value);
}
现在可以了。