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 *` 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
2条答案
按热度按时间lf5gs5x21#
是否有任何选项可以提取
Option<&mut Foo>
外部的可变引用。是的,但是要防止消耗
Option
需要付出一些努力,因为&mut T
不是Copy
。让我们假设您有一个
Option<&mut Foo>
,它是Some
。(这同样适用于非-Some
选项,只是用适当的匹配替换unwrap()
。)例如:opt.unwrap()
会给予你&mut Foo
,但是它会把它移出Option
,因为&mut Foo
不是Copy
:这将使
Option
无法使用,即使mut_ref
超出作用域,我们不希望这样,我们希望 * 借用 * 选项的内部,并在删除借用后保留Option
的使用,为此我们可以使用Option::as_mut
:这里有两点需要注意:首先,您需要使用
as_mut()
,而不是您尝试使用的as_ref()
,因为as_ref()
会在共享引用后面给予您一个可变引用,这会使它变得无用;其次,展开as_mut()
返回一个&mut &mut Foo
,而不是我们想要的&mut Foo
。自动解引用允许调用接受&mut Foo
的函数:如果出于某种原因需要一个实际的
&mut Foo
,人们会认为可以通过解引用&mut &mut Foo
来获得它。因为
*
试图解引用&mut &mut Foo
并提取底层的&mut Foo
,所以不能编译,但是&mut Foo
不是Copy
,所以这是试图“移出一个可变引用”,rustc会告诉你不能这样做。但是,在这种情况下,它可以,你需要执行一个显式的reborrow,即将EXPR
转到&mut *EXPR
,其中EXPR
计算为可变引用。&mut *EXPR
将创建一个对同一数据的 new 可变引用。它不算作别名,因为旧的可变引用将(静态不可用),直到删除新的引用。这基本上与允许 projection 在可变引用上工作的机制相同(即let x_ref = &mut point.x
,其中point
是&mut Point
)-但应用于对象本身。使用显式重借时,它如下所示:
Playground
yruzcnhs2#
正确的方法是使用
as_mut()
方法。需要注意的一点是,您需要满足
&mut self
参数类型,关键的一点是,如果您拥有Option<&mut Foo>
值,则可以安全地将其转换为mut
版本(因为您是它的唯一拥有者)。因此,总体而言,您可以执行以下操作:
Playground