【问题标题】:Type inference and borrowing vs ownership transfer类型推断和借用与所有权转移
【发布时间】:2023-03-19 17:39:02
【问题描述】:

我正在学习 Rust,但我遇到了一些令人困惑的行为。以下代码可以正常编译并按预期工作(编辑:添加了测试功能以外的代码,之前省略了):

struct Container<'a> {
    contents : &'a mut i32,
}

fn main() {
    let mut one = Container { contents: &mut 5 };
    test(&mut one);
    println!("Contents: {}",one.contents);
}

fn test<'a>(mut x : &'a mut Container) {
    *x.contents += 1;
    let y = x;
    *y.contents += 1;
    x = y;
    println!("{:?}",*x.contents)
}

现在在声明中

let y = x;

类型是推断出来的。因为x&amp;'a mut Container 类型,所以我认为这是等价的:

let y: &'a mut Container = x;

但是当我这样做时,编译器会出现问题:

test_3.rs:25:5: 25:10 error: cannot assign to `x` because it is borrowed
test_3.rs:25     x = y;
                 ^~~~~
test_3.rs:23:33: 23:34 note: borrow of `x` occurs here
test_3.rs:23     let y: &'a mut Container = x;

在正确工作的示例中,x 如何没有被借用?我通过从正确工作的版本中省略行 x = y; 进行测试,编译器说:

test_3.rs:24:13: 24:14 note: `x` moved here because it has type `&mut Container<'_>`, which is moved by default

因此,当我没有明确定义类型而是借用时,我会采取行动。发生了什么,我如何在显式给出类型时获得与以前相同的行为,以及在一种情况下导致移动行为但在另一种情况下借用的原因是什么?

已编辑完整程序

【问题讨论】:

标签: rust ownership


【解决方案1】:

当你这样做时

let y = x;

一个动作发生了。 x 被清空,可以这么说,所有权转移到y

当你做任何一个时

let y: &mut _ = x;
let y: &'a mut _ = x;

x 被重新借用以帮助匹配生命周期。这大致翻译为

let y: &mut _ = &mut *x;
let y: &'a mut _ = &mut *x;

这使得x 非空,持有一个别名可变借用。因此,分配给它必须等待y 被销毁。或者,您可以预先移动它

let tmp = x;
let y: &'a mut _ = tmp;

我承认这是不明显的行为,很遗憾你不能在不借用整个值的情况下借用一个值的内容。

【讨论】:

  • 持有一个别名可变借用——我的印象是这显然是安全 Rust 禁止的事情?
  • Rust 不禁止别名可变借用 - 它禁止一次使用多个借用,或以非词法方式重叠它们。当你写 &amp;mut x 时,x 仍然是一个有效的堆栈位置——读取或写入它是不合法的。
  • 有趣。我一直想知道编译器使用什么确切规则来确定 move-vs-reborrow。到目前为止,我认为重借只发生在函数调用 &amp;mut 的函数调用中。但显然,更明确的 within 函数也有资格重新借用。
猜你喜欢
  • 2015-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 2017-08-28
相关资源
最近更新 更多