变量绑定:移动& mut或借用指示物?

时间:2015-05-29 17:21:25

标签: rust

此代码在let c = a;处出现错误,编译错误"使用移动的值:a":

fn main() {
    let a: &mut i32 = &mut 0;
    let b = a;
    let c = a;
}

a被移入b并且不再可用于c的赋值。到目前为止,非常好。

但是,如果我只是注释b的类型并将其他所有内容保留下来:

fn main() {
    let a: &mut i32 = &mut 0;
    let b: &mut i32 = a;
    let c = a;
}

代码在let c = a;

再次失败

但这一次有一个非常不同的错误消息:"无法移出a,因为它是借来的......借用*a在这里:let b: &mut i32 = a;&# 34;

所以,如果我只是注释b的类型:a没有移动到b,而是一个" re" -borrow of *a

我错过了什么?

干杯。

1 个答案:

答案 0 :(得分:7)

  

所以,如果我只注释b的类型:a没有移动到b,而是*a的“重新”借用?

     

我错过了什么?

绝对没有,因为在这种情况下,这两个操作在语义上非常相似(如果ab属于同一范围,则等效)。

  • 您可以将引用a移至b,使a成为移动的值,并且不再可用。
  • 您可以在*a中重新展示b,只要a在范围内,b就无法使用。

第二种情况不如第一种情况明确,你可以通过将定义b的行放入子范围来证明这一点。

此示例无法编译,因为移动了a

fn main() {
    let a: &mut i32 = &mut 0;
    { let b = a; }
    let c = a;
}

但是这一个会,因为一旦b超出范围a,就会解锁:

fn main() {
    let a: &mut i32 = &mut 0;
    { let b = &mut *a; }
    let c = a;
}

现在,对于“为什么注释b的类型会改变行为?”这个问题,我的猜测是:

  • 当没有类型注释时,操作是一个简单而直接的动作。无需进行任何检查。
  • 当存在类型注释时,可能需要转换(将&mut _转换为&_,或将简单引用转换为对特征对象的引用)。因此,编译器选择重新借用值,而不是移动。

例如,此代码非常有效:

fn main() {
    let a: &mut i32 = &mut 0;
    let b: &i32 = a;
}

此处将a移动到b中没有任何意义,因为它们属于不同的类型。这段代码仍在编译:{{1​​}}只是重新借用b,只要*a在范围内,a就无法透明地提供该值。