我有一个包含一些值作为起点的结构,请参阅以下工作代码片段:
struct SomeBigStructWithValues {
values: Vec<isize>,
other_big_crazy_stuff: usize,
}
impl SomeBigStructWithValues {
fn merge(&mut self, other: &Self){
for (_i, val) in other.values.iter().enumerate() {
self.values.push(val-0);
}
}
}
fn main() {
let mut a = SomeBigStructWithValues { values: vec![0, 1], other_big_crazy_stuff: 1<<10 };
loop {
let b = SomeBigStructWithValues { values: vec![2, 3, 4], other_big_crazy_stuff: 1<<10 };
a.merge(&b);
break;
}
println!("{:?}", a.values);
}
首先,我发现借用检查器编译这个很有趣,因为
b
只存在于循环内部,但是 merge
调用使用 b
来修改在循环外部访问的 a.values
。我怀疑借用检查器理解,在 merge
调用内仅发生来自 b.values
的副本,并且在 b
之后不需要从 merge
借用。
现在我想向配置对象添加引用/借用。可悲的是,这破坏了编译。借用检查器会在循环内看到配置对象,并在使用
a.values
时抱怨其生命周期,即使配置本身未在 merge
调用内访问。我对 Rust 很陌生,不明白编译器在这两种情况下的区别。是否有一些终生注释可以使这项工作正常进行?对此行为的任何指示和解释将不胜感激!
#[derive(Clone)]
struct Config{}
const ConfigA: Config = Config{};
const ConfigB: Config = Config{};
struct SomeBigStructWithValues<'a> {
globals: &'a Config,
values: Vec<isize>,
other_big_crazy_stuff: usize,
}
impl SomeBigStructWithValues<'_> {
fn merge(&mut self, other: &Self){
for (_i, val) in other.values.iter().enumerate() {
self.values.push(val-0);
}
}
}
fn main() {
let mut a = SomeBigStructWithValues { globals: &ConfigA, values: vec![0, 1], other_big_crazy_stuff: 1<<10 };
loop {
let localConfig = ConfigB.clone();
// code that changes localConfig
let b = SomeBigStructWithValues { globals: &localConfig, values: vec![2, 3, 4], other_big_crazy_stuff: 1<<10 };
a.merge(&b);
break;
}
println!("{:?}", a.values);
}
编译器输出:
error[E0597]: `localConfig` does not live long enough
--> src/main.rs:26:52
|
24 | let localConfig = ConfigB.clone();
| ----------- binding `localConfig` declared here
25 | // code that changes localConfig
26 | let b = SomeBigStructWithValues { globals: &localConfig, values: vec![2, 3, 4], other_big_crazy_stuff: 1<<10 };
| ^^^^^^^^^^^^ borrowed value does not live long enough
...
29 | }
| - `localConfig` dropped here while still borrowed
30 | println!("{:?}", a.values);
| -------- borrow later used here
Self
是 SomeBigStructWithValues
,与 &self
具有相同的生命周期参数,因此您强制 self
和 other
的内部生命周期相同,但由于 a
可以在块外部访问 b
也必须是蜜蜂。
通过不隐式地为 other
和 self
重用相同的生命周期,可以很容易地修复它,只需替换 Self
,它与 self
的类型完全相同,包括具有相同类型的生命周期参数,但不限于同样的一生,SomeBigStructWithValues
:
fn merge(&mut self, other: &SomeBigStructWithValues){
for (_i, val) in other.values.iter().enumerate() {
self.values.push(val-0);
}
}