我有一个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将引用值移出选项,第二个if let Some(x) = a将导致编译器错误.如果没有第二个if let ...,它可以完美地工作,因此a不必是可变的.

以下是:

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

给出错误:"分配到不可变引用".

这将奏效:

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是必需的,否则我会得到一个错误"不能将不可变的匿名字段(a:std::prelude::v1::Some).0borrow 为可变的".但这感觉不对:a不应该是可变的,因为我没有修改它(见上文).

正确的解决方案是什么?

编辑1

我的问题不同于百分之一百的问题.我希望在Option<&mut T>中多次可变地取消引用,而另一个希望将Option传递给多个函数调用.另一个问题的解决方案不适用于我的情况.

推荐答案

这个呢?

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.

Rust相关问答推荐

生成的future 的 struct 是什么?

按下按钮时如何在服务器中创建文件并在本地下载?

有条件默认实现

如何从使用mockall模拟的方法中返回self?

Rust中的相互递归特性与默认实现

在没有引用计数或互斥锁的情况下,可以从Rust回调函数内的封闭作用域访问变量吗?

Box::new()会从一个堆栈复制到另一个堆吗?

从Type::new()调用函数

在析构赋值中使用一些现有绑定

函数内模块的父作用域的访问类型

铁 rust 中的泛型:不能将`<;T作为添加>;::Output`除以`{Float}`

Rust&;Tokio:如何处理更多的信号,而不仅仅是SIGINT,即SIGQUE?

正则表达式中的重叠匹配?(铁 rust 正则式发动机)

为什么这个变量不需要是可变的?

如何在嵌套的泛型 struct 中调用泛型方法?

如何限制通用 const 参数中允许的值?

为什么 for_each 在释放模式(cargo run -r)下比 for 循环快得多?

为什么我不能克隆可克隆构造函数的Vec?

为什么在 macOS / iOS 上切换 WiFi 网络时 reqwest 响应会挂起?

A 有一个函数,它在 Option<> 类型中时无法编译,但在 Option<> 类型之外会自行编译.为什么?