英文:
Lifetimes in Rust: mut data borrowed
问题
以下代码报告了一个错误:借用的值寿命不够长
fn main() {
let e = 100;
let mut a = (1,);
let mut b = (&e,);
{
let mut c = (&mut a, &mut b);
let f = &mut c;
f.1 .0 = &(f.0 .0);
}
println!("{:?}", b);
}
但以下代码是正确的:
fn main() {
let e = 100;
let a = (1,);
let mut b = (&e,);
{
let mut c = (&a, &mut b);
let f = &mut c;
f.1 .0 = &(f.0 .0);
}
println!("{:?}", b);
}
为什么?!!
第一个代码的完整错误消息:
error[E0597]: `c` does not live long enough
--> src/main.rs:7:17
|
6 | let mut c = (&mut a, &mut b);
| ----- binding `c` declared here
7 | let f = &mut c;
| ^^^^^^ borrowed value does not live enough
8 | f.1 .0 = &f.0 .0;
9 | }
| - `c` dropped here while still borrowed
10 | println!("{:?}", b);
| - borrow later used here
For more information about this error, try `rustc --explain E0597`.
英文:
The following code reports an error:
borrowed value does not live long enough
fn main() {
let e = 100;
let mut a = (1,);
let mut b = (&e,);
{
let mut c = (&mut a, &mut b);
let f = &mut c;
f.1 .0 = &(f.0 .0);
}
println!("{:?}", b);
}
But the following code is correct:
fn main() {
let e = 100;
let a = (1,);
let mut b = (&e,);
{
let mut c = (&a, &mut b);
let f = &mut c;
f.1 .0 = &(f.0 .0);
}
println!("{:?}", b);
}
Why?!!
Full error message for the first code:
error[E0597]: `c` does not live long enough
--> src/main.rs:7:17
|
6 | let mut c = (&mut a, &mut b);
| ----- binding `c` declared here
7 | let f = &mut c;
| ^^^^^^ borrowed value does not live long enough
8 | f.1 .0 = &f.0 .0;
9 | }
| - `c` dropped here while still borrowed
10 | println!("{:?}", b);
| - borrow later used here
For more information about this error, try `rustc --explain E0597`.
答案1
得分: 2
这是因为共享引用是Copy
的,而可变引用不是。
以下是您的代码的简化版本,更容易讨论:
fn main() {
let mut a = 1;
let b;
{
let mut c = &mut a;
// 或者:
let mut c = &a;
let f = &mut c;
b = &**f;
}
println!("{b}");
}
让我们将a
和c
的生命周期分别称为'a
和'c
。因此,f
的类型是&'c mut &'a [mut] i32
。当我们执行b = &**f
时,在可变和不可变版本之间存在差异。
在不可变版本中,我们对f
进行解引用,得到&'a i32
。然后,我们复制这个引用(这是可以的,因为共享引用是Copy
),并得到一个类型为&'a i32
的独立引用。我们可以将这个引用(或它的重新借用版本&*r
)分配给b
,因为a
的生命周期与b
相同。
在可变情况下,我们也对f
进行解引用。但是,我们得到的引用是可变引用:&'a mut i32
。由于可变引用不是Copy
,我们不能将它复制到一个独立的引用中。它必须留在原地,在f
的&'c mut
后面。
然而,我们可以重新借用此引用以创建一个从中派生的引用。但是,当您重新借用类型为&'a mut &'b mut T
的引用时,您无法获得类型为&'b mut T
的引用,只能获得&'a mut T
。否则,您获得的引用可能会超出原始引用的生命周期,并且在您没有权限的情况下存在。
因此,我们得到了**&'c mut i32
**,而不是&'a mut i32
。b
的生命周期超出了c
,因此我们不能将&'c mut i32
(或从中创建的共享&'c i32
)分配给b
。
英文:
This is because shared references are Copy
, while mutable references are not.
Here's a trimmed down version of your code, which is easier to discuss:
fn main() {
let mut a = 1;
let b;
{
let mut c = &mut a;
// Or:
let mut c = &a;
let f = &mut c;
b = &**f;
}
println!("{b}");
}
Let's call the lifetimes of a
and c
'a
and 'c
respectively. Therefore, f
has type &'c mut &'a [mut] i32
. When we do b = &**f
, there is a difference between the mutable and immutable version.
In the immutable version, we dereference f
to get &'a i32
. We then copy this reference (which is fine because shared references are Copy
), and get a freestanding reference of type &'a i32
. We can assign this reference (or the reborrowed version of it, &*r
) to b
, because a
has the same scope b
has.
In the mutable case, we also dereference f
. However, the reference we get is a mutable reference: &'a mut i32
. Since mutable references are not Copy
, we cannot copy it to a freestanding reference. It has to stay where it is, behind the &'c mut
of f
.
What we can do, however, is to reborrow this reference to create a reference descended from it. However, when you reborrow a reference of type &'a mut &'b mut T
, you cannot get a reference of type &'b mut T
, only &'a mut T
. Otherwise, the reference you got could outlive the original reference, and exist while you have no permission for such reference.
Therefore, we get &'c mut i32
, and not &'a mut i32
. b
outlives c
, so we cannot assign a &'c mut i32
(or a shared &'c i32
created from it) to b
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论