Rust的生命周期
老生常谈的生命周期(通识)
生命周期对于静态语言的编程人员并不陌生,以C++举例,虽然再编程时因为习惯不太会把生命周期作为一个重点看,但是再日常使用时我们还是会考虑到引用的生命周期,诸如:
- static变量
- 类中的常规指针
- 类中的shared_ptr,
- 类中的unique_ptr
- 引用的用法
或者一些通识性的错误用法,诸如: - 在函数内部初始化堆内存又使用copy构造函数将其作为返回值传出,造成野指针
- 或在引用作为函数参数时私自释放占用资源造成后续其他位置使用时的异常
一、Rust的生命周期为什么需要单独讨论
- Rust中对于生命周期有自己的特殊标识符如:`a
- Rust中在结合泛型编程以及impl实现时会用到生命周期
- 由于Rust编译器极其严格,而编译器又不是很"聪明",有时需要开发者手动标记生命周期才能编译通过
- 一些疑难的编译问题多数由于生命周期引起
二、从Rust 代码角度看生命周期
Rust 生命周期的写法
rust生命周期的写法与其泛型编程中的泛型类型写法类似,也可以对比C++中的模板写法
C++模板写法:
// 定义一个简单的函数模板,用于打印容器内元素
template <typename T>
void printContainer(const T& container) {
for (const auto& element : container) {
std::cout << element << " ";
}
std::cout << std::endl;
}
Rust中泛型编程的写法:
// 定义一个泛型函数,遍历并打印任何实现了IntoIterator的类型
fn print_items<T>(iterable: T) where T: IntoIterator {
for item in iterable.into_iter() {
println!("{}", item);
}
}
Rust生命周期的写法:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
Rust中的生命周期就像泛型一样,需要在函数上也标注上生命周期,这并不代表函数的生命周期,而是通过此标识符告知编译器,本函数手动标识了生命周期,不要再犯傻。
以上述例子中的生命周期为例:
其中的【'a】并不是代表对x,y的引用,需要x,y是同样的生命周期,比如都需要在同一个大括号中声明和消解。
【'a】意味着,开发者应当意识到,以引用形式传出的返回值的生命周期不应大于x,y 中较小生命周期范围。
善于观察的读者可能想到,是不是正确使用了longest方法就不会出问题,比如在x生命周期中返回x,在y生命周期内返回y
,并不是,编译器依然无法判断。
Rust生命周期的认定规则:
- 若只有一个输入生命周期即只有一个引用类型的函数参数,这个输入生命周期就会被赋给所有的引用类型的返回值
- 每一个引用参数都有自己的生命周期
- 若存在多个输入生命周期,且其中一个是&self或mut self,则&self的生命周期被赋值给所有的返回值(显然这条规则针对于struct的函数实现,类似于类中的方法返回值跟随类对象的生命周期一起存活和消亡)
Rust中的生命周期约束
"不要因为看似复杂的新概念而打退堂鼓,再复杂的问题也终有解决方案"
生命周期约束的写法:
struct Ref<'a, T: 'a> {
r: &'a T
}
形如【T : 'a】,【'b : 'a】,表达的即T or b的作用域范围 >= a;(可以简单类比于生物系统中的父子关系)
随着Rust的升级发展,这样的写法已经几乎不需要人为编写,编译器会自行推导。
NLL(Non-Lexical Lifetime)
引用的生命周期从借用处开始,直到最后一次使用处结束。
'static 生命周期
即将其标记为与整个程序的生命周期一致,一般会在如下场景中使用:
实在编译不过,将函数参数设置为`static,一般情况下还是要看具体的使用场景,尽量避免使用核弹
X、Rust为什么要引入看似复杂的生命周期
Rust以安全著称,引入生命周期的主要作用就是为了避免悬垂引用,而悬垂引用会导致程序引用了本来不该引用的数据,其
是程序崩溃的主要来源之一。
参考文章:
[1] https://course.rs/advance/lifetime/advance.html
[2] https://course.rs/advance/lifetime/static.html
[3] https://course.rs/basic/lifetime.html
[4] https://juejin.cn/post/7326803868326412315
[5] https://doc.rust-lang.org/rust-by-example/scope/lifetime.html
如有勘误,尽情指正。