Reference 可变引用生存期与不可变引用生存期
我有以下代码:Reference 可变引用生存期与不可变引用生存期,reference,rust,immutability,mutable,lifetime,Reference,Rust,Immutability,Mutable,Lifetime,我有以下代码: struct Bar<T> { k: [T; 10], } impl<T> Bar<T> { fn thing(&self, i: usize) -> &T { &self.k[i] } fn thing_mut(&mut self, i: usize) -> &mut T { &mut self.k[i] }
struct Bar<T> {
k: [T; 10],
}
impl<T> Bar<T> {
fn thing(&self, i: usize) -> &T {
&self.k[i]
}
fn thing_mut(&mut self, i: usize) -> &mut T {
&mut self.k[i]
}
}
struct Foo<'a, T: 'a> {
bar: &'a Bar<T>,
count: usize,
}
impl<'a, T> Foo<'a, T> {
fn get(&mut self) -> Option<&'a T> {
if self.count < 10 {
let thing = self.bar.thing(self.count);
self.count += 1;
Some(thing)
} else {
None
}
}
}
struct FooMut<'a, T: 'a> {
bar: &'a mut Bar<T>,
count: usize,
}
impl<'a, T> FooMut<'a, T> {
fn get(&mut self) -> Option<&'a mut T> {
if self.count < 10 {
let thing = self.bar.thing_mut(self.count);
self.count += 1;
Some(thing)
} else {
None
}
}
}
为什么不可变的编译得很好,而可变的编译得不好?在
FooMut
案例中是否缺少一些终生注释?我已经看到了很多关于生命周期和引用的答案,但在本例中,我特别询问了可变与不可变的情况。不可变和可变引用的生命周期方面已经在不同的地方进行了讨论:
请参阅问题的注释和答案中的参考资料
我在这里写了一些关于这个具体案例的笔记,希望能对锈蚀寿命这一困难的概念有所启发
(至少对我来说这很难)
考虑一下这个片段,它是一个简化版本,暴露了问题的相同问题:
struct Foo<'a> {
x: &'a mut i32,
}
impl<'b> Foo<'b> {
fn x(&mut self) -> &'b mut i32 { self.x }
}
fn main() {
let y = &mut 5; // <- 'a(1)
let mut f = Foo { x: y }; // 'a(1) <- 'b(2)
println!("x is: {}", f.x()); // 'a(1) 'b(2) <- 'anonymous(3)
}
我们看到,'anonymous
的生命周期比'b
的生命周期要窄(请参见代码注释中的“近似”生命周期可视化):借用的内容self.x
的生命周期不足以满足生锈安全规则
现在很明显,解决方案应该是通过显式注释减少生命周期,或者在规则的支持下更好地减少生命周期:
有关更多详细信息,请参阅。我相信您的问题已由回答。如果不是这样,或者很可能会回答。请解释您的问题与这些现有问题的不同之处。如果不是,我们可以将此标记为已回答。谢谢您的回答。“如果内部引用是不可变的,则编译器可以确保不会因缩小生存期范围而出现内存问题。”。你所说的“缩小寿命范围”是什么意思?self.x不应该有f实例的生存期吗?哪个变量的生存期范围缩小了?
self.x
(意指引用self.x的生存期)和对Foo
的引用,因为Foo::x(&mut self)
的&self参数可能有不同的生存期。关于缩小生命周期范围的含义,请参见我的更新,我希望它可能更清楚。
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src/main.rs:6:30
|
6 | fn x(&self) -> &'b i32 { self.x }
| ^^^^^^
|
note: ...the reference is valid for the lifetime 'b as defined on the impl at 5:1...
--> src/main.rs:5:1
|
5 | impl<'b> Foo<'b> {
| ^^^^^^^^^^^^^^^^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 6:5
--> src/main.rs:6:5
|
6 | fn x(&self) -> &'b i32 { self.x }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
struct Foo<'a> {
x: &'a mut i32,
}
impl<'b> Foo<'b> {
fn x(&mut self) -> &mut i32 { self.x }
}
fn main() {
let y = &mut 5; // <- 'a
let mut f = Foo { x: y }; // 'a <- 'b
println!("x is: {}", f.x()); // 'a 'b
}
let mut my_ref: &mut i32 = &mut 1;
let mut f = Foo { x: my_ref };
{ | <--- narrowed lifetime scope
let y = &mut 5; |
f.x = y; |
} | <---
// ERROR: invoking f.x() when self.x is no more valid!
f.x();