gpt4 book ai didi

rust - 如何在不将可变引用传递给函数的情况下重新借用它?

转载 作者:行者123 更新时间:2023-11-29 07:46:05 26 4
gpt4 key购买 nike

我发现了一个案例,手动内联一个函数会改变借用检查器对待它的方式,以至于它不再编译。据推测,它依赖于函数签名中的信息。我如何在内联版本中提供此信息?

我认为它是如何工作的

'a'b'a'b 短的生命周期(可以是写成 'b: 'a).

假设我有一个p: &'b mut f32。我可以简单地借用 p(使用 &mut p)来获得 q: &'a mut &'b mut f32

  1. 我是否正确理解 &'a mut &'b mut f32 等同于 &'a mut &'a mut f32 因为 'b: 'a?

然后我可以取消引用 q(使用 *q)以获得 r: &'a mut f32。我可以通过 r(使用 *r = something)写入 f32,我可以稍后(在生命周期之外 'a) 通过p(使用*p)读回值。

使用函数调用

这是我认为使用上述序列的一些工作代码:

fn reborrow<'a, 'b: 'a>(q: &'a mut &'b mut f32) -> &'a mut f32 {
*q
}

fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let q = &mut p;
let r = reborrow(q);
*r = 2.718;
}
assert_eq!(*p, 2.718);
}

(在 reborrow() 的主体中用 q 替换 *q 也可以,因为如果缺少必要的取消引用,Rust 会插入).

手动内联

如果我手动内联 reborrow() 调用,它将不再编译:

fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let q = &mut p;
let r = *q; <-- ERROR REPORTED HERE.
*r = 2.718;
}
assert_eq!(*p, 2.718);
}
error[E0507]: cannot move out of borrowed content
  1. 谁拿走了我的玩具?什么是类型推断思维/缺失?

  2. 我能否以某种方式注释 let 绑定(bind)以使编译器推断出与以前版本相同的类型?

其他一些尝试

这是另一个有效的版本,但没有定义名称 r:

fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let q = &mut p;
**q = 2.718;
}
assert_eq!(*p, 2.718);
}

这里有一个解决方法,它定义了名称 r 并且可以工作,但不使用相同的借用和取消引用序列:

fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let q = &mut p;
let r = &mut **q;
*r = 2.718;
}
assert_eq!(*p, 2.718);
}

我做了一个playground结合所有四个版本。

最佳答案

正如人们所期望的那样,显而易见的解决方案有效:

fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let r: &mut f32 = p;
*r = 2.718;
}
assert_eq!(*p, 2.718);
}

这看起来相对直观,也是我希望新手最终得到的结果。


但是,如果您开始考虑它,它就没有意义了。如前所述,它看起来像:

  • let r: &mut f32 = p;移出 p
  • 但我们稍后在 assert_eq!(*p, 2.718);
  • 中使用了 p

一个合理的解释是pCopy,但它不是1!

答案是,隐含地,Rust 正在幕后执行重新借用。即显式代码为:

fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let r: &mut f32 = &mut *p;
*r = 2.718;
}
assert_eq!(*p, 2.718);
}

我们可以通过在重新借用后尝试读取 p 来检查这一点,并检查编译器错误:

error[E0502]: cannot borrow `p` as immutable because `*p` is also borrowed as mutable
--> <anon>:6:24
|
5 | let r: &mut f32 = p;
| - mutable borrow occurs here
6 | println!("{}", p);
| ^ immutable borrow occurs here
7 | *r = 2.718;
8 | }
| - mutable borrow ends here

error: aborting due to previous error

这证实 p 确实只是可变地借用,而不是移动、克隆或复制。

1 可变引用不能复制甚至克隆,因为它会违反支撑 Rust 安全性的别名 XOR 可变性原则.

关于rust - 如何在不将可变引用传递给函数的情况下重新借用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43036156/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com