第五节、生命周期
生命周期
在“引用和借用”部分没有讨论的一个细节是,Rust 中的每个引用都有一个生命周期,这是该引用有效的范围。大多数时候,生命周期是隐含的和推断的,就像大多数时候,类型是推断的。当可能有多种类型时,我们必须注释类型。以类似的方式,当引用的生命周期可以以几种不同的方式相关时,我们必须注释生命周期。Rust 要求我们使用通用生命周期参数来注释关系,以确保在运行时使用的实际引用肯定是有效的。
其他语言有作用域问题,和这个概念类似
{
let r;
{
let x = 5;
r = &x;
}
println!("r: {}", r);
}
{
let r; // ---------+-- 'a
// |
{ // |
let x = 5; // -+-- 'b |
r = &x; // | |
} // -+ |
// |
println!("r: {}", r); // |
} // ---------+
如果此时修改一个打印语句的位置,代码就可以编译通过
{
let x = 5; // ----------+-- 'b
// |
let r = &x; // --+-- 'a |
// | |
println!("r: {}", r); // | |
// --+ |
} // ----------+
函数引用参数生命周期
fn main() {
let string1 = String::from("abcd");
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("The longest string is {}", result);
}
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
x
} else {
y
}
}
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
结构体中定义的生命周期
struct ImportantExcerpt<'a> {
part: &'a str,
}
fn main() {
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence = novel.split('.').next().expect("Could not find a '.'");
let i = ImportantExcerpt {
part: first_sentence,
};
}
省略的生命周期
fn first_word(s: &str) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
fn first_word<'a>(s: &'a str) -> &'a str {
静态寿命 我们需要讨论的一个特殊生命周期是'static,这意味着这个引用可以在整个程序期间都存在。所有字符串文字都有'static生命周期,我们可以如下注释:
let s: &'static str = "I have a static lifetime.";
'static您可能会在错误消息中看到使用生命周期的建议。但在指定'static引用的生命周期之前,请考虑您拥有的引用是否实际上存在于程序的整个生命周期中。您可能会考虑是否希望它活得那么久,即使它可以。大多数情况下,问题是由于尝试创建悬空引用或可用生命周期不匹配造成的。在这种情况下,解决方案是解决这些问题,而不是指定'static生命周期。