从Option<& mut T>读取参考文献。多次

时间:2017-02-18 21:12:12

标签: rust

我有Option<&mut T>并希望多次访问包含的引用,如下所示:

fn f(a: Option<&mut i32>) {
    if let Some(x) = a {
        *x = 6;
    }
    // ...
    if let Some(x) = a {
        *x = 7;
    }
}

fn main() {
    let mut x = 5;
    f(Some(&mut x));
}

这不起作用,因为if let Some(x) = a将参考值移出Option,第二个if let Some(x) = a将导致编译器错误。没有第二个if let ...,这可以完美地运作,因此a不必是可变的。

以下内容:

if let Some(ref x) = a {
    **x = 6;
}

给出错误:&#34;赋值给不可变引用&#34;。

这样可行:

fn f(mut a: Option<&mut i32>) {
    if let Some(ref mut x) = a {
        **x = 6;
    }
    if let Some(ref mut x) = a {
        **x = 7;
    }
}

mut a是必要的,否则我会收到错误&#34;无法将不可变的匿名字段(a:std::prelude::v1::Some).0借用为可变的&#34;。但这感觉不对:a不应该是可变的,因为我没有修改它(见上文)。

什么是正确的解决方案?

编辑1

我的问题与How to pass `Option<&mut ...>` to multiple function calls without causing move errors?中的问题不同。我希望在Option<&mut T>中多次重新引用引用,而另一个想要将Option传递给多个函数调用。其他问题的解决方案不适用于我的情况。

1 个答案:

答案 0 :(得分:4)

这个怎么样?

fn f(a: Option<&mut i32>) {
    if let Some(&mut ref mut x) = a {
        *x = 6;
    }
    // ...
    if let Some(&mut ref mut x) = a {
        *x = 7;
    }
}

在这种情况下,a不需要是可变的。

&mut ref mut感觉有点尴尬,但这是有道理的:首先我们通过解构删除&mut,然后再次对该值进行可变引用。当我们不使用Option

时,这一点更为明显
let mr: &mut Vec<u32> = &mut vec![];
{
    let &mut ref mut a = mr;
    a.push(3);
}
mr.push(4);

这也有效。第三行(特殊)相当于:

let a = &mut     *mr   ;
//               ^^^----- this is an lvalue of type `Vec<u32>`
//      ^^^^^^^^^^^^----- together it's of type `&mut Vec<u32>` again

Option案例中,我们无法使用&mut *X版本,但需要在模式中执行所有操作。因此&mut ref mut x