生命周期
- Rust 中每一個引用都有其生命周期织堂,也就是引用保持有效的作用域颓遏。大部分時候生命周期都是隱含并可以推斷的狸剃,有點類似 rust 的類型推斷付枫。
- 生命周期的主要目標(biāo)是避免懸垂指針烹玉,這點應(yīng)該 rust 優(yōu)勢吧,可以將一些
- Rust 編譯器使用借用檢查器來檢查生命周期是否有效阐滩。
fn main(){
let r;
{
let x = 5;
r = &x;
}
println!("r = {}",r);
}
Rust 之所以大家愿意放棄 cpp 而投身到 rust 的原因就是 rust 能夠兼顧效率和安全二打。安全是在編譯過程檢查。
|
5 | r = &x;
| ^^^^^^ borrowed value does not live long enough
6 | }
| - `x` dropped here while still borrowed
7 |
8 | println!("r = {}",r);
| - borrow later used here
這個應(yīng)該不難理解叶眉,r 是指向 x 的內(nèi)存地址的引用址儒,x 在離開作用域 會 drop 掉 x 內(nèi)存,也就是釋放 r 所引用的內(nèi)存衅疙,所以當(dāng)離開莲趣。
函數(shù)中生命周期
fn longest(x:&str,y:&str) -> &str {
if x.len() > y.len(){
x
}else{
y
}
}
--> src/main.rs:1:30
|
1 | fn longest(x:&str,y:&str) -> &str {
| ^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
傳入 x 和 y 都是引用,返回也是引用饱溢,為了保證返回的引用不是懸垂指針喧伞,所以告訴編譯器生命周期需要滿足參數(shù)的生命周期要大于返回值生命周期。
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("hello");
let s2 = String::from("world");
let res = longest(s1.as_str(), s2.as_str());
println!("res = {}",res);
}
看起來有點特殊绩郎,聲明一下生命周期潘鲫。這也就是說明 rust 在編譯過程的安全性。
fn get_str<'a>(x: &'a str, y: &str) -> &'a str{
x
}
因為 get_str
返回值 str zhi'y
fn get_str_one<'a>(x:&'a str,y:&'a str) -> &'a str{
let r = String::from("hello");
r.as_str()
}
結(jié)構(gòu)體聲明周期
#[derive(Debug)]
struct Tut {
title: &str,
}
#[derive(Debug)]
struct Tut<'a> {
title: &'a str,
}
#[derive(Debug)]
struct Tut<'a> {
title: &'a str,
}
fn main(){
let s1 = String::from("hello");
let s2 = String::from("world");
let res = longest(s1.as_str(), s2.as_str());
println!("res = {}",res);
let vue = String::from("vue");
let vueTut = Tut{title:&vue};
println!("a = {:#?}",vueTut)
}
生命周期省略
- 沒有生命周期注解卻能夠編譯肋杖,rust 團隊將很明確的模式進行簡化即使不聲明生命周期
fn get_str_two(s:&str) -> &str{
s
}
-
編譯器會根據(jù)可以省略生命周期聲明的 3條規(guī)則來推斷生命周期溉仑,如果不滿足就會要求開放人員指定生命周期給出錯誤提示,還要補充說明一點就是生命周期注解省略規(guī)則適用于 fn 定義和 impl 塊定義状植。
開始介紹 3 個省略原則前浊竟,介紹用于理解規(guī)則的兩個概念輸入生命周期和輸出生命周期怨喘,函數(shù)或方法的參數(shù)的生命周期稱為輸入生命周期。而返回值的生命周期稱為輸出生命周期振定。- 每一個引用的參數(shù)都有自己生命周期參數(shù)
一個引用參數(shù)函數(shù)必怜,fn foo<'a>(x:&'a u32)
兩個引用參數(shù)的函數(shù)fn bar<'a,'b>(x: &'a u32, y:&'b u32)
- 如果只有一個輸入生命周期參數(shù),那么被賦予所有輸出生命周期參數(shù)
fn foo(x:&i32)->&i32
就等價于fn<'a>(x:&a' i32)-> &'a i32
- 如果方法有多個輸入生命周期參數(shù)后频,不過其中之一因為方法的緣故為&self或者&mut self 那么self 的生命周期被賦予所有輸出生命周期參數(shù)梳庆,例子在下面來看
- 每一個引用的參數(shù)都有自己生命周期參數(shù)
#[derive(Debug)]
struct Tut<'a> {
title: &'a str,
}
impl<'a> Tut<'a>{
fn do_something(&self)->i32{
3
}
}
fn main(){
let react = String::from("react");
let reactTut = Tut{title:&react};
println!("{}",reactTut.do_something());
}
在 do_something
方法里沒有聲明生命周期,
impl<'a> Tut<'a>{
fn do_something(&self)->i32{
3
}
fn do_something_1(&self,s:&str)->&str{
self.title
}
fn do_something_2(&self,s:&str)->&str{
s
}
}
impl<'a> Tut<'a>{
fn do_something(&self)->i32{
3
}
fn do_something_1(&self,s:&str)->&str{
self.title
}
fn do_something_2<'b>(&self,s:&'b str)->&'b str{
s
}
}
靜態(tài)生命周期
定義方式'static
,其生命周期存活于整個程序期間卑惜,所有的字符字面值都擁有static 生命周期膏执。有點類似全局變量。
use std::fmt::Display;
fn func<'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 func<'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
}
}
let str1 = String::from("vue");
let str2 = String::from("react");
let ann = 129;
let res = func(str1.as_str(), str2.as_str(), ann);