一文弄懂rust生命周期
作者:int8
生命周期是Rust语言中的一个概念,用于决内存安全问题,本文主要介绍了一文弄懂rust生命周期,具有一定的参考价值,感兴趣的可以了解一下
一、生命期是什么
生命期,又叫生存期,就是变量的有效期。
实例1
{ let r; { let x = 5; r = &x; } println!("r: {}", r); }
编译错误,原因是r所引用的值已经被释放。
上图中的绿色范围’a表示r的生命期,蓝色范围’b表示x的生命期。
实例2
fn longer(s1: &String, s2: &String) -> &String { if s2.len() > s1.len() { s2 } else { s1 } } fn main() { let r; { let s1 = "rust".to_string(); let s2 = "ecmascript".to_string(); r = longer(&s1, &s2); } println!("{} is longer", r); }
longer函数取s1和s2两个字符串较长的一个返回其引用值。但这段代码不会通过编译,原因是最后使用r的时候,s1和s2都已经失效了。虽然可以把r的使用移到s1和s2的生命期以内避免错误,但对于函数来说,它并不知道调用者如何使用它,所以为了保障自己传递出去的值始终是可使用的,就要消除一切危险,直接不能通过编译。
所以下面代码编译错误
fn longer(s1: &String, s2: &String) -> &String { if s2.len() > s1.len() { s2 } else { s1 } } fn main() { let r; { let s1 = "rust".to_string(); let s2 = "ecmascript".to_string(); r = longer(&s1, &s2); println!("{} is longer", r); } }
二、标明生命期
虽然生命期的含义是变量的有效期,但其实只应用于引用。
一些场景,必须显式标明引用的生命期。
标明生命期,并不是改变引用的有效期,只是显式告诉编译器引用的有效期。悬垂引用的问题还存在,还需要程序员自己处理。
(一)生命期注释是标明引用生命期的办法。
语法格式:
用单引号开头,跟着生命期名字:
&i32 // 常规引用 &'lifea i32 // 含有生命期注释的引用 &'lifeb mut i32 // 含有生命期注释的可变引用
(二)特殊生命期
'static
'static表示的生命期是从程序运行开始到程序运行结束。
所有字符串字面量都是 &'static str
三、使用生命期
(一)函数中使用生命期
改造longer函数:
fn longer<'a>(s1: &'a String, s2: &'a String) -> &'a String { if s2.len() > s1.len() { s2 } else { s1 } } fn main() { let r; { let s1 = "rust".to_string(); let s2 = "ecmascript".to_string(); r = longer(&s1, &s2); println!("{} is longer", r); } }
我们把生命期作为泛型参数,标明函数返回值的生命期与两个参数的生命期是一样的,这样就能编译通过了。意思是只要返回值和参数的生命期一样时,就能使用longer函数。
(二)结构体中使用生命期
fn main() { struct Str<'a> { content: &'a str } let s = Str { content: "string_slice" }; println!("s.content = {}", s.content); } 方法定义 impl<'a> Str<'a> { fn get_content(&self) -> &str { self.content } }
这里返回值并没有标明生命期,但是加上也无妨。这是一个历史问题,早期Rust不支持生命期自动判断,所有的生命期必须严格声明,但现在的Rust已经支持了。
到此这篇关于一文弄懂rust生命周期的文章就介绍到这了,更多相关rust生命周期内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!