无法从 &mut self 借用文件(错误消息:无法移出借用的内容)
Can't borrow File from &mut self (error msg: cannot move out of borrowed content)
use std::fs::File;
use std::io::Read;
pub struct Foo {
maybe_file: Option<File>,
}
impl Foo {
pub fn init(&mut self) {
self.maybe_file = Some(File::open("/proc/uptime").unwrap());
}
pub fn print(&mut self) {
let mut file = self.maybe_file.unwrap();
let mut s = String::new();
file.read_to_string(&mut s).unwrap();
println!("Uptime: {}", s);
}
}
fn main() {}
编译它会给我:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:14:24
|
14 | let mut file = self.maybe_file.unwrap();
| ^^^^ cannot move out of borrowed content
为什么会这样?我该怎么做才能解决它?
self
在 print
中的类型为 &mut Foo
,也就是说,它是对 Foo
类型值的借用可变引用。 Rust 中的类型默认移动所有权,也就是说,按值取值将使源静态无效并阻止程序员再次使用它(除非它被重新初始化)。在这种情况下,unwrap
具有签名:
impl Option<T> {
fn unwrap(self) -> T { ...
也就是说,它正在按值获取 Option
值,从而试图消耗它的所有权。因此,self.maybe_file.unwrap()
试图使用 maybe_file
中的数据,这将使 self
指向部分无效数据(之后使用 maybe_file
字段是非法的)。编译器无法通过借用的引用强制执行此操作,因为它们可以指向任何地方,因此必须始终有效,因此移出是非法的。
幸运的是,可以避免这个问题:as_ref
method creates an Option<&T>
out of an &Option<T>
and the as_mut
方法从 &mut Option<T>
中创建一个 Option<&mut T>
。生成的 Option
不再位于引用之后,因此通过 unwrap
:
使用它是合法的
let mut file = self.maybe_file.as_mut().unwrap();
这略有不同,因为 file
具有类型 &mut File
而不是 File
,但幸运的是 &mut File
是其余代码所必需的。
完成这项工作的另一种方法是使用手动模式匹配:
match self.maybe_file {
Some(ref mut file) => println!(...),
None => panic!("error: file was missing")
}
这与 .as_mut().unwrap()
做的事情完全相同,只是更明确一点:ref mut
创建一个直接指向 self.maybe_file
占用的内存的引用,就像 as_mut
.
use std::fs::File;
use std::io::Read;
pub struct Foo {
maybe_file: Option<File>,
}
impl Foo {
pub fn init(&mut self) {
self.maybe_file = Some(File::open("/proc/uptime").unwrap());
}
pub fn print(&mut self) {
let mut file = self.maybe_file.unwrap();
let mut s = String::new();
file.read_to_string(&mut s).unwrap();
println!("Uptime: {}", s);
}
}
fn main() {}
编译它会给我:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:14:24
|
14 | let mut file = self.maybe_file.unwrap();
| ^^^^ cannot move out of borrowed content
为什么会这样?我该怎么做才能解决它?
self
在 print
中的类型为 &mut Foo
,也就是说,它是对 Foo
类型值的借用可变引用。 Rust 中的类型默认移动所有权,也就是说,按值取值将使源静态无效并阻止程序员再次使用它(除非它被重新初始化)。在这种情况下,unwrap
具有签名:
impl Option<T> {
fn unwrap(self) -> T { ...
也就是说,它正在按值获取 Option
值,从而试图消耗它的所有权。因此,self.maybe_file.unwrap()
试图使用 maybe_file
中的数据,这将使 self
指向部分无效数据(之后使用 maybe_file
字段是非法的)。编译器无法通过借用的引用强制执行此操作,因为它们可以指向任何地方,因此必须始终有效,因此移出是非法的。
幸运的是,可以避免这个问题:as_ref
method creates an Option<&T>
out of an &Option<T>
and the as_mut
方法从 &mut Option<T>
中创建一个 Option<&mut T>
。生成的 Option
不再位于引用之后,因此通过 unwrap
:
let mut file = self.maybe_file.as_mut().unwrap();
这略有不同,因为 file
具有类型 &mut File
而不是 File
,但幸运的是 &mut File
是其余代码所必需的。
完成这项工作的另一种方法是使用手动模式匹配:
match self.maybe_file {
Some(ref mut file) => println!(...),
None => panic!("error: file was missing")
}
这与 .as_mut().unwrap()
做的事情完全相同,只是更明确一点:ref mut
创建一个直接指向 self.maybe_file
占用的内存的引用,就像 as_mut
.