答: 不能。
我觉得前面的回答都不能解决这位题主的疑惑 。我想了一个有点绕的例子,来说明编译器是不能自动推断出generic lifetime的,因为可行的标注方法不只一种(楼上那个longest例子从逻辑上看似乎只剩下一种标注方法了,所以不具有足够的说服力)。
如下面定义的函数根据短字符串的长度来截取长字符串,该函数因为没有标注lifetime无法成功编译:
fn cut_long_according_to_short(l: &str, s: &str) -> &str {
let len = s.len();
&l[0..len]
}
有两种不同的标注方法可以实现成功编译,编译器无法自动推断出该采用哪一个。
第一种比较宽松:
fn cut_long_according_to_short<'a>(l: &'a str, s: &str) -> &'a str {
let len = s.len();
&l[0..len]
}
第二种比较严格:
fn cut_long_according_to_short<'a>(l: &'a str, s: &'a str) -> &'a str {
let len = s.len();
&l[0..len]
}
但是两者最终实现的语义是有区别的。后者不仅要求返回引用的lifetime不得超过l,而且要求也不得超过s。
我们可以验证这二者的区别。例如我们会发现如果采用第一种宽松的标注法,下面的代码是可以成功编译的;反之如果采用第二种严格的标注法,则下面的代码无法编译:
fn main() {
let result;
let string1 = String::from("The loooooooong");
let l = string1.as_str();
{
let string2 = String::from("The short");
let s = string2.as_str();
result = cut_long_according_to_short(l, s);
}
println!("{result}");
}
这是由于string2的lifetime小于result,在println!行运行前就被drop掉了(注意string2被括号{}限定在一个更小的scope内)。这在第一种较宽松的标注中是被允许的,而被第二种严格的标注所禁止。
