为什么可变引用没有移到这里?

时间:2015-08-22 09:15:42

标签: rust move-semantics

我的印象是可变引用(即&mut T)总是被移动。这是完全合理的,因为它们允许独占的可变访问。 在下面的代码中,我为另一个可变引用分配了一个可变引用,并移动了原始引用。结果我再也不能使用原文了:

let mut value = 900;
let r_original = &mut value;
let r_new = r_original;
*r_original; // error: use of moved value *r_original

如果我有这样的功能:

fn make_move(_: &mut i32) {
}

并修改我的原始示例,如下所示:

let mut value = 900;
let r_original = &mut value;
make_move(r_original);
*r_original; // no complain

当我用它调用函数r_original时,我希望可移动的引用make_move被移动。然而,这不会发生。我仍然能够在通话后使用该参考。

如果我使用通用函数make_move_gen

fn make_move_gen<T>(_: T) {
}

并将其称为:

let mut value = 900;
let r_original = &mut value;
make_move_gen(r_original);
*r_original; // error: use of moved value *r_original

再次移动引用,因此程序的行为与我期望的一样。 调用函数make_move时为什么不移动引用?

Code example

2 个答案:

答案 0 :(得分:6)

实际上可能有充分的理由。

&mut T 实际上不是类型:所有借用都是通过某些(可能无法形容的)生命周期进行参数化的。

当写一个

fn move_try(val: &mut ()) {
    { let new = val; }
    *val
}

fn main() {
    move_try(&mut ());
}

类型推理引擎推断typeof new == typeof val,因此它们共享原始生命周期。这意味着new的借款在val借款之前不会结束。

这意味着它相当于

fn move_try<'a>(val: &'a mut ()) {
    { let new: &'a mut _ = val; }
    *val
}

fn main() {
    move_try(&mut ());
}

但是,当你写

fn move_try(val: &mut ()) {
    { let new: &mut _ = val; }
    *val
}

fn main() {
    move_try(&mut ());
}

投射发生 - 同样的事情让你抛弃指针可变性。这意味着生命周期是一些(看似无法指定)'b < 'a。这涉及一个演员,因此是一个再借,所以再借不能超出范围。

永远重新出现的规则可能更好,但明确的声明不会太成问题。

答案 1 :(得分:2)

我在这些问题here上问了一些问题。

似乎在一些(很多?)案例中,不是移动,而是进行再借款。不违反内存安全性,只有“移动”值仍然存在。我也找不到关于这种行为的任何文档。

@Levans打开了一个github问题here,虽然我并不完全相信这只是一个文档问题:可靠地移出一个&amp; mut引用似乎是Rust的所有权方法的核心。