生命周期

他再也無法明白自己要什么,因為人的生命只有一次,我們既不能把它與我們以前的生活相比較,也無法使其完美之后再來度過。

思考下面的這個例子:

//拋出錯誤:error[E0106]: missing lifetime specifier
fn main(){
    let line:&str = "lang:en=hello world";
    let lang:&str = "en";
    let v:&str;
    {
        v = skip_prefix(line, lang);
    }
    println!("{}", v);
}

fn skip_prefix(par1:&str, par2:&str) -> &str{//expected lifetime parameter
    par1
}
//this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `par1` or `par2`

對于上面的那個例子,我們的編譯器會報錯,目前為止我也還是搞不明白。我的困惑就是,既然我們的函數(shù)明確指出來了返回的應(yīng)該是par1這個引用的話,那么為什么報錯信息里面還說什么不確定返回的到底是par1還是par2呢?這個問題留到以后更加明白的時候在解決吧。

1.使用生命周期來糾正上面的那個例子

利用生命周期的語法改寫上面那個例子的話,那么就不會再報錯了??匆幌聦懛ň烤故窃趺礃樱?/p>

fn main(){
    let line:&str = "lang:en=hello world";
    let lang:&str = "en";
    let v:&str;
    {
        v = skip_prefix(line, lang);
    }
    println!("{}", v);//lang:en=hello world
}

fn skip_prefix<'a, 'b>(par1:&'a str, par2:&'b str) -> &'a str{
    par1
}

但是如果你怎樣做的話那么就是不對的了:

//拋出錯誤:error[E0312]: lifetime of reference outlives lifetime of borrowed content...
fn main(){
    let line:&str = "lang:en=hello world";
    let lang:&str = "en";
    let v:&str;
    {
        v = skip_prefix(line, lang);
    }
    println!("{}", v);
}

fn skip_prefix<'a, 'b>(par1:&'a str, par2:&'b str) -> &'b str{
    //the reference is valid for the lifetime 'b as defined on the body
    par1
}

2.語法

'a讀作生命周期a。技術(shù)上講,每一個引用都有一些與之相關(guān)的生命周期,不過編譯器再通常情況下允許對其進(jìn)行省略。生命周期的聲明需要放在<>里面,<>里面所支持的是一種泛型參數(shù),生命周期也是泛型參數(shù)當(dāng)中的一種。聲明周期的使用就直接更在類型前面就OK了。你需要幾個聲明周期去顯式利用,就顯式聲明多少個,對于函數(shù)而言,顯示聲明的周期的個數(shù)與函數(shù)參數(shù)無關(guān)。下面舉一個例子:

fn main(){
    let line:&str = "lang:en=hello world";
    let lang:&str = "en";
    let num:i32 = 3;
    let v:&str;
    {
        v = skip_prefix(line, &num);
    }
    println!("{}", v);//lang:en=hello world
}

fn skip_prefix<'a>(par1:&'a str, par2:&i32) -> &'a str{
    par1
}

下面就聲明周期的使用舉幾個例子:

  • 1.&'a mut i32:一個帶有聲明周期'a的i32的可變引用
  • 2.&'b str:一個帶有聲明周期'b的str的不可變引用

3.結(jié)構(gòu)體與生命周期的碰撞

當(dāng)我們定義結(jié)構(gòu)體時,我們也會需要顯式的生命周期。這是為什么呢?假如有一個結(jié)構(gòu)體A的話,那么我們需要確保任何A的引用必須比結(jié)構(gòu)成員活的更短,否則就有可能造成dangling pointer。下面看看具體用法:

fn main(){
  let num:&i32 = &9;
  let struct_obj:Foo = Foo{n: num};
  println!("{}", struct_obj.n);
}
struct Foo<'a>{
  n: &'a i32
}

如果你把生命周期參數(shù)給去掉的話,那么將會報錯,如下所示:

//報錯信息為:error[E0106]: missing lifetime specifier
fn main(){
  let num:&i32 = &9;
  let struct_obj:Foo = Foo{n: num};
  println!("{}", struct_obj.n);
}
struct Foo{
  n: &i32//expected lifetime parameter
}

4.impl塊與生命周期的碰撞

當(dāng)在impl塊中使用生命周期的時候應(yīng)該這樣使用:

fn main(){
  let num:&i32 = &9;
  let struct_obj:Foo = Foo{n: num};
  println!("{}", struct_obj.get_n());
}
struct Foo<'a>{
  n: &'a i32
}
impl<'a> Foo<'a>{
  fn get_n(&self) -> &'a i32{self.n}
}

5.理解作用域

從代碼的結(jié)構(gòu)來看,我們可以看出變量的作用域所起始的地方也大致能夠看出變量的作用域所結(jié)束的地方。對于這種問題所需要注意的是我們的變量一般都是存儲在棧上的,而對于棧來說它的結(jié)構(gòu)特點是:先進(jìn)后出,所以說越早定義的變量那么它是最后出的,因此有這么一個需要注意的事項:先定義的變量不能夠引用后定義的變量,否則由于后定義的變量會首先被銷毀而報錯。舉個簡單的例子:

fn main(){
  let y:&i32 = &9;//y的作用域開始出現(xiàn)
                  //|
                  //|
}                 //y離開它的作用域

分析下面這個例子:

//error: borrowed value does not live long enough
fn main(){
  let num1:&i32;
  {
    let num2:&i32 = &9;
    let foo:Foo = Foo{x: num2};
    num1 = foo.get_x();
  }//temporary value dropped here while still borrowed
}
struct Foo<'a>{
  x: &'a i32
}
impl<'a> Foo<'a>{
  fn get_x(&self) -> &'a i32{self.x}
}

問題就是出在前面提到的那點:先定義的變量引用了后定義的那個變量。由于后定義的變量先一步被銷毀,但是先定義的那個變量仍舊需要和其進(jìn)行綁定,所以報錯。
這個問題,如果要修改的話,那么可以利用static關(guān)鍵字:

fn main(){
  let num1:&i32;
  {
    static TEMP:i32 = 9;
    let num2:&i32 = &TEMP;
    let foo:Foo = Foo{x: num2};
    num1 = foo.get_x();
  }
  println!("{}", num1);//9
}
struct Foo<'a>{
  x: &'a i32
}
impl<'a> Foo<'a>{
  fn get_x(&self) -> &'a i32{self.x}
}

6.'static

'static生命作用域是一個特殊的作用域,它具有橫跨整個程序的生命周期。下面介紹一下簡單用法:

let str:&'static str = "hello world!";
static FOO:i32 = 5;
let num:&i32 = &FOO;

END

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容