为什么编译器错误抱怨多个可变引用而不是悬挂引用?
Why does the compiler error complain about multiple mutable references not dangling reference?
我想了解当函数重新借用可变引用时到底发生了什么。
fn main() {
let mut a = String::new();
let mut b = String::new();
let aa = &mut a;
let c = my_fun(aa, &mut b);
let d = &mut a;
println!("{}", c);
}
fn my_fun<'b>(x: &'b mut String, y: &'b mut String) -> &'b mut String { y }
根据我的理解,my_fun
将 aa
重新借用为 &*aa
,其范围将是 my_fun
。但是由于我在函数签名中创建的生命周期限制,重新借用应该至少在 &mut b
存在时存在。所以 println
强制重新借用直到它。
这不应该在 free 之后抛出一个使用错误,因为匿名重借的范围只在 my_fun
内吗?在这个函数之外,这个引用应该是无效的。
但我得到的错误是:
error[E0499]: cannot borrow `a` as mutable more than once at a time
--> src/main.rs:7:13
|
5 | let aa= &mut a;
| ------ first mutable borrow occurs here
6 | let c = my_fun(aa, &mut b);
7 | let d = &mut a;
| ^^^^^^ second mutable borrow occurs here
8 | println!("{}", c);
| - first borrow later used
如果可变引用只是被复制而不是在函数内部重新借用,这将是有意义的。
我相信你在这里“重新借用”想得太多了。
您应用的生命周期要求表明,return 值引用的事物至少具有参数引用事物的生命周期。这是真的(如果不能证明是真的,这将无法编译)。所以不可能有悬空引用。
没有单独的“重借”引用。借用是编译器内部的簿记,以跟踪生命周期。没有 let x = &*aa
实际发生或什至特别暗示的步骤。这不像引用计数,内存在运行时实际发生变化。
在 my_fun
内部,y
是作用域为函数的引用。但是 return 值 仅限于调用者。 (如果不是这样,函数将无法使用,与 &mut
无关。)
From my understanding the my_fun
reborrows aa
as &*aa
whose scope would be the my_fun
.
不完全是这样。
让我们回顾一下:为什么要重新借用?
&T
和&mut T
有一个根本的区别:&T
是Copy
,而&mut T
甚至不是Clone
。结果是 &mut T
只能被 移动 因此调用如:
let x: &mut T = /*...*/;
func(x);
会导致 x
在调用后无法使用。解决方法是引入一个临时的:
let x: &mut T = /*...*/;
let tmp = &mut *x;
func(tmp);
这个临时对象会重新借用 x
的指针,并被 func
使用。
还有...那是再借!编译器内置了这个纯粹为了人体工程学的“临时”创建!
考虑到这一点,让我们回到:
From my understanding the my_fun
reborrows aa
as &*aa
whose scope would be the my_fun
.
寿命通常是 范围 而不是 点 ,这里也是如此。
上面示例中 tmp
的生命周期受到两种方式的限制:
- 不能大于
x
。
- 不能小于
func
。
这是另一种说法,它可以是这些界限之间的 任何东西。
我想了解当函数重新借用可变引用时到底发生了什么。
fn main() {
let mut a = String::new();
let mut b = String::new();
let aa = &mut a;
let c = my_fun(aa, &mut b);
let d = &mut a;
println!("{}", c);
}
fn my_fun<'b>(x: &'b mut String, y: &'b mut String) -> &'b mut String { y }
根据我的理解,my_fun
将 aa
重新借用为 &*aa
,其范围将是 my_fun
。但是由于我在函数签名中创建的生命周期限制,重新借用应该至少在 &mut b
存在时存在。所以 println
强制重新借用直到它。
这不应该在 free 之后抛出一个使用错误,因为匿名重借的范围只在 my_fun
内吗?在这个函数之外,这个引用应该是无效的。
但我得到的错误是:
error[E0499]: cannot borrow `a` as mutable more than once at a time
--> src/main.rs:7:13
|
5 | let aa= &mut a;
| ------ first mutable borrow occurs here
6 | let c = my_fun(aa, &mut b);
7 | let d = &mut a;
| ^^^^^^ second mutable borrow occurs here
8 | println!("{}", c);
| - first borrow later used
如果可变引用只是被复制而不是在函数内部重新借用,这将是有意义的。
我相信你在这里“重新借用”想得太多了。
您应用的生命周期要求表明,return 值引用的事物至少具有参数引用事物的生命周期。这是真的(如果不能证明是真的,这将无法编译)。所以不可能有悬空引用。
没有单独的“重借”引用。借用是编译器内部的簿记,以跟踪生命周期。没有 let x = &*aa
实际发生或什至特别暗示的步骤。这不像引用计数,内存在运行时实际发生变化。
在 my_fun
内部,y
是作用域为函数的引用。但是 return 值 仅限于调用者。 (如果不是这样,函数将无法使用,与 &mut
无关。)
From my understanding the
my_fun
reborrowsaa
as&*aa
whose scope would be themy_fun
.
不完全是这样。
让我们回顾一下:为什么要重新借用?
&T
和&mut T
有一个根本的区别:&T
是Copy
,而&mut T
甚至不是Clone
。结果是 &mut T
只能被 移动 因此调用如:
let x: &mut T = /*...*/;
func(x);
会导致 x
在调用后无法使用。解决方法是引入一个临时的:
let x: &mut T = /*...*/;
let tmp = &mut *x;
func(tmp);
这个临时对象会重新借用 x
的指针,并被 func
使用。
还有...那是再借!编译器内置了这个纯粹为了人体工程学的“临时”创建!
考虑到这一点,让我们回到:
From my understanding the
my_fun
reborrowsaa
as&*aa
whose scope would be themy_fun
.
寿命通常是 范围 而不是 点 ,这里也是如此。
上面示例中 tmp
的生命周期受到两种方式的限制:
- 不能大于
x
。 - 不能小于
func
。
这是另一种说法,它可以是这些界限之间的 任何东西。