rust - 为什么编译器错误会抱怨多个可变引用而不是悬空引用?
问题描述
我试图了解当函数重新借用可变引用时究竟会发生什么。
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
强制reborrow活到它为止。
这不应该在 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
如果可变引用只是被复制而不是在函数内部重新借用,这将是有意义的。
解决方案
据我了解,
my_fun
重新借用aa
的&*aa
范围将是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
。
而且……那是再借!编译器内置了这个“临时”创建,纯粹是为了符合人体工程学!
考虑到这一点,让我们回到:
据我了解,
my_fun
重新借用aa
的&*aa
范围将是my_fun
.
生命周期通常是一个范围而不是一个点,这在这里是正确的。
tmp
在我上面的例子中,生命周期受到两种方式的限制:
- 它不能大于
x
。 - 不能小于
func
。
这是另一种说法,它可以是这些界限之间的任何东西。
推荐阅读
- batch-file - What to fix on my code with two IF conditions inside a FOR loop referencing an environment variable defined by the IF conditions?
- heroku - 我似乎无法用 gunicorn 修复错误,日志如下所示
- php - 从类中导入和别名静态方法
- java - 如何在跟踪进位的同时获得两个数组的总和(如 java 中的 bigInt)?
- android - 我看不到我在布局活动中添加的图片
- regex - 在 PowerShell 中查找和替换字符串的问题
- excel - 添加以日期为名称的工作表
- java - 如果不匹配,则从 ArrayList 流式传输返回 null 错误
- html - 如何实现/上传我自己的html和css代码到weebly?
- ruby-on-rails - 如何将黄瓜与铁轨分开运行?