为什么这里没有移动可变引用? [英] Why is the mutable reference not moved here?

查看:49
本文介绍了为什么这里没有移动可变引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was under the impression that mutable references (i.e. &mut T) are always moved. That makes perfect sense, since they allow exclusive mutable access. In the following piece of code I assign a mutable reference to another mutable reference and the original is moved. As a result I cannot use the original any more:

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) {
}

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

and modify my original example to look like this:

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

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

I would expect that the mutable reference r_original is moved when I call the function make_move with it. However that does not happen. I am still able to use the reference after the call.

如果我使用通用函数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函数时引用没有移动?

The reference is moved again and therefore the program behaves as I would expect. Why is the reference not moved when calling the function make_move?

代码示例

推荐答案

这实际上可能是一个很好的理由.

There might actually be a good reason for this.

&mut T 实际上不是一种类型:所有借用都由某个(可能无法表达的)生命周期参数化.

&mut T isn't actually a type: all borrows are parametrized by some (potentially inexpressible) lifetime.

当一个人写

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

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

类型推断引擎推断 typeof new == typeof val,因此它们共享原始生命周期.这意味着 new 的借用不会结束,直到 val 的借用完成.

the type inference engine infers typeof new == typeof val, so they share the original lifetime. This means the borrow from new does not end until the borrow from val does.

这意味着它等价于

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 cast happens - the same kind of thing that lets you cast away pointer mutability. This means that the lifetime is some (seemingly unspecifiable) 'b < 'a. This involves a cast, and thus a reborrow, and so the reborrow is able to fall out of scope.

始终重新借用规则可能会更好,但显式声明并没有太大问题.

An always-reborrow rule would probably be nicer, but explicit declaration isn't too problematic.

这篇关于为什么这里没有移动可变引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆