2015-08-22 24 views
7

我的印象是可变引用(即&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 

我期望当我使用它调用函数make_move时,可变参考r_original被移动。但是,这并没有发生。通话结束后,我仍然可以使用该参考。

如果我使用一个通用的功能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

显式实例化('make_move :: <&mut i32>(r_original);')像原始函数(不移动)一样工作。迷人;我会假设在类型推断之前进行借用检查。 – Veedrac

+0

从dacker的回答我假设是这样的:显式注释类型是一个可变引用触发内容的重新借用而不是移动,留下原始引用再次可用一旦新引用(这里在make_move的范围)超出范围。 –

回答

5

实际上可能有一个很好的理由。

&mut T不是实际上 a类型:所有借款都是通过一些(可能无法表达的)生命周期参数化的。

当一个写

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。这涉及到一个演员,因此重新出借,所以重新出借能够超出范围。

总是重新出借规则可能会更好,但显式声明不是太成问题。

+0

我从来没有这样想过。不过这似乎合乎逻辑。通过“抛弃指针可变性”,你的意思是从一个可变引用获取共享引用?像let r:&i32 = r_mut;其中r_mut是&mut i32。 –

+0

“通过”抛弃指针可变性“,你的意思是”→是的。 – Veedrac

+0

很好的解释。这真的很有道理。我对“b”的猜测是:它是包含'move_try'的主体的''a'和定义'new'的嵌套范围的交集;所以''b'将会是这个嵌套的作用域,在'''借用结束的时候结束。 – dacker

2

我问沿着这些线路here东西。

看来,在一些(很多?)的情况下,而不是移动,重新借款发生。内存安全不受侵犯,只有“移动”的值仍在。我也找不到有关该行为的任何文档。

@Levans开通了GitHub的问题here,虽然我并不完全相信这仅仅是一个文档的问题:可靠移动了& MUT参考似乎集中于所有权的锈的方法。

相关问题