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

jte*_*epe 10 move-semantics rust

我的印象是可变引用(即&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
Run Code Online (Sandbox Code Playgroud)

如果我有这样的功能:

fn make_move(_: &mut i32) {
}
Run Code Online (Sandbox Code Playgroud)

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

let mut value = 900;
let r_original = &mut value;
make_move(r_original);
*r_original; // no complain
Run Code Online (Sandbox Code Playgroud)

我期望r_originalmake_move用它调用函数时移动可变引用.然而,这不会发生.我仍然可以在通话后使用参考.

如果我使用通用函数make_move_gen:

fn make_move_gen<T>(_: T) {
}
Run Code Online (Sandbox Code Playgroud)

并称之为:

let mut value = 900;
let r_original = &mut value;
make_move_gen(r_original);
*r_original; // error: use of moved value *r_original
Run Code Online (Sandbox Code Playgroud)

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

代码示例

Vee*_*rac 7

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

&mut T是不实际类型:所有借入是由一些(可能难以形容)寿命参数化.

当一个人写道

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

fn main() {
    move_try(&mut ());
}
Run Code Online (Sandbox Code Playgroud)

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

这意味着它相当于

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

fn main() {
    move_try(&mut ());
}
Run Code Online (Sandbox Code Playgroud)

但是,当你写作

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

fn main() {
    move_try(&mut ());
}
Run Code Online (Sandbox Code Playgroud)

一个强制转换 - 同样的东西可以让你抛弃指针的可变性.这意味着生命周期是一些(看似无法指定)'b < 'a.这涉及演员阵容,因此是再利用,因此再扩张能够超出范围.

一个永远重新出现的规则可能会更好,但明确的声明并不是太有问题.


dac*_*ker 5

我在这里问了类似的问题。

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

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