Rust 引用的生命周期应该超过函数的生命周期

4

我有一个小型的解析器,它在解析过程中使用同一个&str:

struct Parser<'a>{
    r: &'a str,
    pos: usize
}

impl<'a, 'b: 'a> Parser<'a>{
    fn new(s: &'b str)->Parser<'a>{
        Parser{r: s, pos:0}
    }
    fn next(&'a self)->Parser<'a>{
        Parser{r: self.r, pos: self.pos + 1}
    }
    fn nnext(&'a self)->Parser<'a>{
        Parser{r: self.r, pos: self.pos + 2}
    }
    fn nnnext(&'a self)->Parser<'a>{
        return self.next().nnext()
    }
}

我会像这样使用它:
fn parse(s: &str){
    let parser = Parser::new(s);
    parser.nnnext();
}

我得到了以下错误:

25 |         return self.next().nnext()
   |                -----------^^^^^^^^
   |                |
   |                returns a value referencing data owned by the current function
   |                temporary value created here

参考文献保证比解析器方法存在时间更长。如何注释生命周期以表达这一点?特别地,为什么 nnnext 不能编译通过?显然,该引用超过了self.next().nnext() 的调用时间。
非常感谢您的帮助。 Hendrik
1个回答

4

使用&'a self会将解析器的生命周期与其引用的字符串的生命周期混淆在一起,这是没有必要的。

如果去掉这个限制,就不再有问题了:

struct Parser<'a>{
    r: &'a str,
    pos: usize
}

impl<'a> Parser<'a>{
    fn new(s: &'a str)->Parser<'a>{
        Parser{r: s, pos:0}
    }
    fn next(&self)->Parser<'a>{
        Parser{r: self.r, pos: self.pos + 1}
    }
    fn nnext(&self)->Parser<'a>{
        Parser{r: self.r, pos: self.pos + 2}
    }
    fn nnnext(&self)->Parser<'a>{
        return self.next().nnext()
    }
}

(我还删除了无用的标签)

它能工作。说实话,我不明白为什么它能工作。如果我使用&'a self,那么它意味着&str有生命周期'a? - Hatatister
1
当你声明fn nnext(&'a self) -> Parser<'a>时,你基本上是在说self的生命周期(即Parser实例)是'a,这也是内部str的生命周期。这就导致了一个问题,即放弃该实例并从中返回一个值。 - Denys Séguret
1
@Hatatister,我认为这个问题的解决方案是将生命周期设定为标记中最短的那个。fn next(&'a self)->Parser<'a>的问题在于通过链式调用在nnnext中创建的临时变量的生命周期比它们所包含的&str引用更短。你真正想要的是与r字段的生命周期绑定的新实例,这就是Denys的解决方案所提供的。这就是为什么它起作用而你的原始代码不起作用。我希望这样能解释清楚了。 - Kevin Anderson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接