Why
lifetime parameter代表着变量的引用的生命周期,在一些代码中,会看到一个函数有多个lifetime变量,如何理解?
考虑这样一个函数
pub struct StrSplit<'a> {remainder: &'a str,delimiter: &'a str,}impl<'a> StrSplit<'a> {pub fn new(haystack: &'a str, delimiter: &'a str) -> Self {Self {remainder: haystack,delimiter,}}pub fn next(&mut self) -> Option<&'a str> {if let Some(next_delim) = self.remainder.find(self.delimiter) {let until_delimter = &self.remainder[..next_delim];self.remainder = &self.remainder[(next_delim + self.delimiter.len())..];Some(until_delimiter)} else if self.remainder.is_empty() {None} else {let rest = self.remainder;self.remainder = "";Some(rest)}}}fn main() {let heystack = "a b c d e".to_string();let letters = StrSplit::new(&heystack, " ");assert_eq!("a", letters.next());}
这里我们定义了一个结构体 StrSplit, 它的两个字段拥有相同的lifetime,乍一看这里没有什么问题,并且从测试函数来看也没问题,但这时候考虑另外一种情况 s
fn until_char(s: &str, c: char) -> Option<&str> {let delimter = format!("{}", c);StrSplit::new(s, &delimter).next()}fn main() {let heystack = "a b c d e".to_string();let res = until_char(&heystack, ' ');assert_eq!("a", res);}
error[E0515]: cannot return value referencing local variable `delimter`--> src/lib.rs:41:5|41 | StrSplit::new(s, &delimter).next()| ^^^^^^^^^^^^^^^^^---------^^^^^^^^| | || | `delimter` is borrowed here| returns a value referencing data owned by the current functionerror: aborting due to previous errorFor more information about this error, try `rustc --explain E0515`.
这个错告诉我们,返回值引用了local variable, 但是返回值明明引用的明明是heystack, 为什么说引用了delimter?因为我们在初始化StrSplit的时候告诉compiler, haystack: &'a str, delimiter: &'a str haystack, delimiter拥有相同的lifetime,如果这两个参数lifetime不一样,那么编译器会选择最短的那个lifetime,在这个例子中,编译器发现 delimter的liftime在until_char这个函数结束后就销毁了,所以编译器选择了delimter的lifetime,并且由于next的返回值的lifetime也是 ‘a, 所以编译器认为 next的返回值和delimter的lifetime一致。
那要如何修改这个函数来解决这个问题?
在这里引入一个新的lifetime
pub struct StrSplit<'a, 'b> {remainder: &'a str,delimiter: &'b str,}impl<'a, 'b> StrSplit<'a, 'b> {pub fn new(haystack: &'a str, delimiter: &'b str) -> Self {Self {remainder: haystack,delimiter,}}}
这样就告诉编译器,haystack和delimiter的liftime不一致,但是返回值的lifetime和haystack一样。
