繁体   English   中英

传递 Option<&mut T> 时何时需要 mut

[英]When is mut required when passing an Option<&mut T>

我有一个 function,我需要在其中传递一个结构,进行一些操作,然后将结果推送到结构中。 该结构可能存在也可能不存在,因此在我将可变引用传递给 function 之前,我将其包装在一个选项中。简化后它类似于以下内容。

似乎有两种不同的编写方式,我试图理解为什么变量 a 需要可变,即使我没有直接修改它

struct Foo {
    value: Vec<i32>,
}

fn bar(a: Option<&mut Foo>) {
    <do_stuff>
    while <condition> {
    <do_stuff>
        if let Some(&mut ref mut x) = a {
            x.value.push(value);
        }
    }
}

在 bar &mut 中需要传入 if let

fn bar2(mut a: Option<&mut Foo>) {
    <do_stuff>
    while <condition> {
        <do_stuff>
        if let Some(ref mut x) = a {
            x.value.push(value);
        }
    }
}

在 bar2 中,a 需要在 function 声明中定义为可变的

fn bar3(a: Option<&mut Foo>){
    if let Some(x) = a {
        x.value.push(0);
    }
}

我不认为它与正在修改的 a 中的值有关,因为没有循环 (bar3) 的相同过程不需要 a 可变。

据我了解,在 if let 语句上使用“ref mut”应该可以防止 Option 内的值在块内移动。 由于循环,这是必需的。 由于循环,是否也需要 a 的可变性? 我确信取消引用和重新共享会发生一些我在这里不理解的事情。

我意识到可能有更好的方法来做到这一点,但我只是在试图更好地理解借用的工作原理。

我很惊讶第一个代码示例完全有效,但我会尝试分解语法以查看其功能:

  •  let a: Option<&mut Foo> =...; if let Some(x) = a { x.value.push(0); }

    这是可行的,因为分配会将值移动并将所有权转移到左侧。 这不需要原始值是可变的。 在这种情况下,左侧将Option解构为Some(x) ,其中x&mut Foo


  •  let a: Option<&mut Foo> =...; if let Some(ref mut x) = a { x.value.push(0); }

    如果不可变,这将无法工作,因为它试图可变地引用Option a内部值( x将是&mut &mut Foo )并且如果变量本身不可变,您将无法获得对变量字段的可变引用。


  •  let a: Option<&mut Foo> =...; if let Some(&mut x) = a { x.value.push(0); }

    这不是您的示例之一,但无论如何我都需要对其进行解释。 这是行不通的。 当解构时&mut做什么本质上反映了它匹配的内容。 在这里,您将尝试将类型&mut Foo与声明&mut x相匹配; &mut s 取消并且x将是Foo类型。 这当然会失败,因为除非它实现Copy ,否则您无法从引用中获取拥有的值。


  •  let a: Option<&mut Foo> =...; if let Some(&mut ref mut x) = a { x.value.push(0); }

    这很有趣,因为我不希望这些规则以这种方式相互作用,但我们就在这里。 似乎首先应用匹配&mut _的规则,以便ref mut x然后与Foo值(未移动)匹配,这具有将x声明为&mut Foo的效果。 最终结果是a的内部值被可变地重新借用,而a本身是可变的。

    这是安全的,因为您a . 如果您使用&Option<&mut Foo>尝试它,那么您会收到一条错误消息,指示您无法通过共享引用进行变异。


如果您正在寻找有经验的意见,我会简单地这样做并称之为一天:

let mut a: Option<&mut Foo> = ...;
if let Some(x) = &mut a {
    x.value.push(0);
}

这与您的bar2样本几乎相同,只是写法略有不同。 ref / ref mut的使用大多已经过时了,因为引入了匹配人体工程学,这使得它们几乎没有必要(除了一些模糊的情况)。 如果我将来需要它,我会记住这种模式:)。

那么, “[使用] Option<&mut T> 时什么时候需要 mut” Option的所有非消耗方法授予对其内部值的可变访问权限(需要可变地使用它或可变地重新借用它)需要&mut访问Option 所以答案几乎总是如此,除非您发现情况并非如此(因为它不依赖于 function 调用)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM