a、Rust中每一个引用都有其生命周期,也就是引用保持有效的作用域。
大部分时候生命周期是隐含并可以推断的,正如大部分时候类型可以推断一样
b、生命周期的主要目标是避免悬垂引用。
c、Rust编译器使用借用检查器来检查生命周期是否有效
1. 函数中的生命周期
// fn longest(x: &str, y: &str) -> &str {
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let s1 = String::from("abcde");
let s2 = String::from("ab");
let r = longest(s1.as_str(), s2.as_str());
println!("r = {}", r);
}
// 结果: r = abcde
- 结构体中的生命周期
//1、结构体中的生命周期
#[derive(Debug)]
struct A<'a> { //结构体中引入生命周期
name: &'a str,
}
fn main() {
let n = String::from("hello");
let a = A{name: &n};
println!("a = {:?}", a);
let s = get_a_str(&n);
println!("s = {}", s);
}
//2、生命周期省略
fn get_a_str(s: &str) -> &str {
s
}
// 结果:
// a = A { name: "hello" }
// s = hello
//(1)没有生命周期注解却能够编译,原因:早期的rust中必须显式的声明生命周期,后来rust团队将很明确的模式进行了注解的简化。
//(2)遵守生命周期省略规则的情况下能明确变量的声明周期,则无需明确指定生命周期。函数或者方法的参数的生命周期称为输入生命周期,而返回值的生命周期称为输出生命周期。
//(3)编译器采用三条规则判断引用何时不需要生命周期注解,当编译器检查完这三条规则后仍然不能计算出引用的生命周期,则会停止并生成错误。
//(4)生命周期注解省略规则适用于fn定义以及impl块定义,如下:
// a、每个引用的参数都有它自己的生命周期参数。例如如下:
// 一个引用参数的函数,其中有一个生命周期: fn foo<'a>(x: &'a i32)
// 两个引用参数的函数,则有两个生命周期 :fn foo<'a, 'b>(x: &'a i32, y: &'b i32)
// 以此类推。
// b、如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数:
// fn foo(x: &i32) -> &i32 等价于 fn foo<'a>(x: &'a i32) -> &'a i32
// c、如果方法有多个输入生命周期参数,不过其中之一因为方法的缘故为&self或者&mut self,那么self的生命周期被赋予所有输出生命周期参数。例子在下面来看。
// fn function(&self, x: &str, y: &str, ....) -> &str
3. 方法中的生命周期
// 方法中的生命周期
struct StuA<'a> {
name: &'a str,
}
impl <'b> StuA<'b> {
fn do_thing(&self) -> i32 { //标量不用考虑生命周期.
3
}
fn do_thing2(&self, s: &str) -> &str { // 返回值&str 的生命周期 按照 &self 的来定义
self.name
}
fn do_thing3<'c>(&self, s: &'c str) -> &'c str {
s // 这里的返回值, 需要标注生命周期, 编译器会根据返回值推导生命周期
}
}
fn main() {
let s = String::from("hello");
let a = StuA{name: &s};
println!("thing = {}", a.do_thing());
let s2 = String::from("worldworld");
println!("thing2 = {}", a.do_thing2(&s2));
println!("thing3 = {}", a.do_thing3(&s2));
}
// 结果:
// thing = 3
// thing2 = hello
// thing3 = worldworld
4. 静态生命周期
//1、静态生命周期
//定义方式: 'static
//其生命周期存活于整个程序期间,所有的字符字面值都拥有static生命周期。
//let s: &'static str = "hello";
//
use std::fmt::Display;
fn function<'a, T: Display>(x: &'a str, y: &'a str, ann: T) -> &'a str {
println!("ann is {}", ann);
if x.len() < y.len() {
x
} else {
y
}
}
fn main() {
let s1 = String::from("i am s1");
let s2 = String::from("i am s2");
let ann = 129;
let r = function(s1.as_str(), s2.as_str(), ann);
println!("r = {}", r);
println!("s1 = {} , s2 = {}", s1, s2);
}
// 结果:
// ann is 129
// r = i am s2
// s1 = i am s1 , s2 = i am s2
网友评论