是否有选项可以从 Option<&mut Foo>
中提取可变引用?
我找到的只有 as_ref()
,它提取了一个不可变引用。
有没有办法从
Option<&mut Foo>
中提取可变引用。
有的,但需要一些努力来防止使用Option
时出现错误,因为&mut T
不是Copy
类型。
我们假设你有一个Option<&mut Foo>
,它是Some
。(如果是非Some
选项,则将unwrap()
替换为适当的匹配即可。)例如:
let mut foo = Foo;
let mut opt = Some(&mut foo);
opt.unwrap()
将会给你一个&mut Foo
,但它会把它从Option
中移动出来,因为&mut Foo
不是Copy
类型:
let mut_ref = opt.unwrap();
drop(mut_ref); // done with mut_ref
println!("{:?}", opt); // XXX doesn't compile, opt is consumed
Option
在 mut_ref
超出作用域后无法使用。我们不想这样,我们想要借用选项内部并在放弃借用后保留对 Option
的使用。为此,我们可以使用Option :: as_mut
:let mut_ref_ref = opt.as_mut().unwrap();
drop(mut_ref_ref);
println!("{:?}", opt); // compiles
这里有两个需要注意的地方:首先,你需要使用 as_mut()
而不是你尝试使用的 as_ref()
,因为 as_ref()
会给你一个可变引用后面跟着一个共享引用,这使其无用。第二,解包 as_mut()
会返回一个 &mut &mut Foo
,而不是我们想要的 &mut Foo
。它非常接近 - 例如,自动解引用允许你调用一个接受 &mut Foo
的函数:
fn wants_ref(_r: &mut Foo) {}
let mut_ref_ref = opt.as_mut().unwrap(); // got &mut &mut Foo
wants_ref(mut_ref_ref); // but we can send it to fn expecting &mut Foo
如果你因某种原因想要一个真正的&mut Foo
,那么你应该通过对&mut &mut Foo
进行解引用来获得它。然而,这样做是行不通的:
// XXX doesn't compile
let mut_ref = *opt.as_mut().unwrap();
*
试图对&mut &mut Foo
进行取消引用,并提取底层的&mut Foo
。但是&mut Foo
不是Copy
,所以这就是企图“移出可变引用”的行为,而rustc将告诉您这是不允许的。但是,在这种情况下可以这样做,您需要执行显式reborrow,也就是将EXPR
转换为&mut *EXPR
,其中EXPR
计算为可变引用。 &mut *EXPR
将创建对相同数据的新可变引用。这不算别名,因为旧的可变引用会(静态地不可用)直到新的可变引用被丢弃。这基本上是允许在可变引用上工作的投影机制(即let x_ref = &mut point.x
,其中point
是&mut Point
)- 但应用于对象本身。
使用显式reborrow如下:
// `&mut *` is reborrow, and `*` dereferences `&mut &mut Foo`
let mut_ref = &mut **opt.as_mut().unwrap();
wants_ref(mut_ref);
println!("{:?}", opt); // opt is still usable
as_mut()
方法进行操作。&mut self
参数类型。关键观察是,如果你拥有一个Option<&mut Foo>
值,你可以安全地将其转换为同一类型的mut
版本(因为你是它唯一的所有者)。
也就是说,你可以自由地从Option<&mut Foo>
(所有权,不可变)转换为mut Option<&mut Foo>
(所有权,不可变),然后在其上调用.as_mut()
以达到&mut Foo
(引用,可变)。let maybe_foo: Option<&mut Foo> = Some(&mut foo);
let mut maybe_foo = maybe_foo;
if let Some(mutable_reference_to_foo) = maybe_foo.as_mut() {
...
}
&'static mut Foo
的情况吗? - Denys Séguretas_mut()
并不返回可变引用,它只是将&mut Option<Foo>
转换为Option<&mut Foo>
。我需要的是一种方法来从Option<&mut Foo>
中提取&mut Foo
。 - fptech20Option
或Result
,那么使用?
运算符提取内部值而不需要任何样板代码。 - Alexey LarionovOption
是Some
,那么不美观的&mut **opt.as_mut().unwrap()
将从Option<&mut Foo>
中提取出&mut Foo
。(第二个*
是为了解引用&mut &mut Foo
,而&mut *
是显式重新借用,它提取可变引用而不移动它。)https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7af28c1073275a9232c08436b3c21e63 - user4815162342