首页 > 解决方案 > 生锈寿命说明符的问题

问题描述

考虑以下程序:

fn func(source: &str, state: & Vec<&str>) {
    println!("{}", source);
    println!("{}", state[0]);
}
fn step<'a>(source: &'a str, state: &mut Vec<&'a str>) {
    state.push(&source[4..10]);
    func(source, state);
    state.push(&source[4..10]);
}
fn main() {
    let source = "abcdefghijklmnopqrstuvwxyz";
    {
        let mut state = Vec::<&str>::new();
        step(source, &mut state);
        step(source, &mut state);
        step(source, &mut state);
    }
}

这编译并运行没有错误。我完全可以理解为什么这里需要生命周期说明符 'a,否则你可以运行:

fn main() {
    let mut state = Vec::<&str>::new();
    {
        let source = "abcdefghijklmnopqrstuvwxyz";
        step(source, &mut state);
        step(source, &mut state);
        step(source, &mut state);
    }
    println!("{}", state[0]);
}

这将导致未定义的输出。我的问题是我想将“func”的两个参数打包到一个结构中,但我无法做到这一点:

struct MyStruct<'a, 'b> {
    pub source: &'a str,
    pub state: &'b mut Vec<&'b str>,
}
fn func(arg: MyStruct) {
    println!("{}", arg.source);
    println!("{}", arg.state[0]);
}
fn step<'a>(source: &'a str,
            state: &mut Vec<&'a str>) {
    state.push(&source[4..10]);
    let s = MyStruct{source: source, state: state};
    func(s);
    state.push(&source[4..10]);
}
fn main() {
    let source = "abcdefghijklmnopqrstuvwxyz";
    {
        let mut state = Vec::<&str>::new();
        step(source, &mut state);
        step(source, &mut state);
        step(source, &mut state);
    }
}

上面的代码无法编译并出现错误消息:

107 |             state: &mut Vec<&'a str>) {
    |             ----- consider changing the type of `state` to `&'a mut std::vec::Vec<&'a str>`
108 |     state.push(&source[4..10]);
109 |     let s = MyStruct{source: source, state: state};
    |                                             ^^^^^ lifetime `'a` required

如果我将 state 更改为 &'a mut Vec<&'a str>,则构建失败并显示以下消息:

117 |         step(source, &mut state);
    |                           ----- first mutable borrow occurs here
118 |         step(source, &mut state);
    |                           ^^^^^ second mutable borrow occurs here
119 |         step(source, &mut state);
120 |     }
    |     - first borrow ends here

如果有人能告诉我如何完成这项工作,我将不胜感激。

注意:在这个示例程序中,“source”是一个具有静态生命周期的字符串。在“真实”程序中,“源”没有静态生命周期,而是程序在运行时读取的文件内容。“源”的寿命与“状态”一样长或更长

标签: rustlifetime

解决方案


函数参数的生命周期情况如下:

fn step<'a>(source: &'a str,
            state: &mut Vec<&'a str>)

让我们命名在生命周期中没有显式名称的引用:

fn step<'a, 'x>(source: &'a str,
                state: &'x mut Vec<&'a str>)

在那里,现在所有引用都有明确的生命周期,我们可以看到结构中的配置与它们在函数参数中的相互关系不对应。

如果您的结构应该遵循我们想要的相同关系:

struct MyStruct<'a: 'x, 'x> {
    pub source: &'a str,
    pub state: &'x mut Vec<&'a str>,
}

由于这是一个类型定义,我们需要添加函数中隐含的关系,即'a: 'x“'a 比 'x”更有效</p>

请记住,您还需要s限定 MyStruct 类型的变量所持有的借用范围——它可变地借用状态(可变地意味着排他地)。因此,您需要在 with 行周围插入范围let s = ..f(s)以便s在下一步调用之前结束范围:

{
    let s = MyStruct{source: source, state: state};
    func(s);
}

推荐阅读