具有借用值作为成员的结构的生命周期如何受此借用的影响?

问题描述 投票:0回答:1

我有一个包含一些值作为起点的结构,请参阅以下工作代码片段

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
rust borrow-checker
1个回答
0
投票

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);
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.