2015-08-26 42 views
1

此函數不會編譯,因爲它試圖返回v0,它已被移至指定爲v1的位置。我明白那個。指定給移動的變量似乎「否定」移動

fn testvec() -> Vec<i64> { 
    let mut v0 = vec![0,1,2]; 
    let v1 = v0; 
    //v0 = vec![1,2,3]; 
    v0 
} 

但是,如果我取消v0作業的註釋,它將進行編譯。這背後的原則是什麼?有記錄嗎?

當我第一次發現這種行爲時,函數看起來像這樣。它的行爲與上述相同,但我也懷疑嵌套塊是否有所作爲。

fn testvec() -> Vec<i64> { 
    let mut v0 = vec![0,1,2]; 
    { 
     let v1 = v0; 
     //v0 = vec![1,2,3]; 
    } 
    v0 
} 

UPDATE

總結我的困惑:我想到了一個「移動」實際上是由變量名訪問。但實際上只有變量的內容變得不可訪問。例如。這個編譯器錯誤是誤導性的:v0 moved here because - 它聽起來像變量名稱被移動,而不僅僅是它的值。

回答

7

v0v1想象成可以包含一個小部件的紙板箱。

隨着let mut v0 = vec![0, 1, 2];創建與黑色記號筆寫在其一側標籤「V0」的標籤說:「內容:一個Vec<i64>」一個紙板箱在其一側,並把標記窗口小部件「[0,1,2] 「 在裏面。 (這個「mut」在盒子上變成了一個粘性的貼紙,說你可以調整存儲在裏面的東西,例如把一個新的元素放到矢量上,或者扔掉矢量並放置一個新的元素。)

使用let v1 = v0;,您創建另一個紙板盒,這個盒子帶有標籤「v1」(和另一個「內容:一個Vec<i64>」標籤),並將該部件從「v0」框中取出並放入「 v1「框。 (沒有用mut聲明的v1紙板盒在盒子的側面變成了一個粘性的標籤,說只允​​許您從盒子中取出小部件,而不是放入任何東西。「不適用於重複使用「,它的意思是,也許翻蓋包裝對於這樣的事情會更好一些,只要注意不要讓剪刀損傷自己)

v0紙板箱現在不包含任何控件,所以」內容:一個Vec<i64>「是不正確的,直到它再次成立爲止,你不能從盒子中拿出任何東西或使用盒子的內容,對嗎?如果您詢問其內容,例如指定v0作爲該函數的返回值,編譯器會對你大喊,因爲它知道紙板箱中不會有小部件。

如果你在一個嵌套塊中聲明瞭v1紙箱,當你到達該塊的末尾時,用口袋噴火器將v1紙板箱和任何東西燒壞。

如果您編寫了v0 = vec![1, 2, 3],則您正在創建一個新標籤,標籤爲「[1,2,3]」,並將其放入標有v0的紙板箱中。編譯器,按照說明書,可以看到,在函數結束時,v0紙板箱將始終包含一個小部件,因此它可以讓您將其作爲值返回。


運用類比:

fn testvec() -> Vec<i64> { 
    let mut v0 = vec![0,1,2]; 
    let v1 = v0; 
    v0 = vec![1,2,3]; 
    v0 
} 

這是一個指令片材,其讀取大致是這樣的:

  1. 該指令片被稱爲「testvec」和使一個Vec<i64>部件。

  2. 取一個紙箱,在其側面寫上「v0」。

    製作一個[0, 1, 2]小部件並將其放入v0框中。

  3. 取一個紙箱,在其側面寫上「v1」。

    [0, 1, 2]窗口部件從v0框中取出並放入v1框中。

  4. 製作一個[1, 2, 3]小部件並將其放入(現在爲空)v0框中。

  5. 從v0框中取出小部件:它是此說明書的最終產品。

    哦,我們不再需要那個v1盒子,所以把它和它所包含的小部件燒掉。

+1

* pocket flamebrower * =>我在哪裏可以找到一個? –

+1

@MatthieuM:對不起,這是受限制的信息。 –

+0

我應該如何考慮「移動」作爲*內容*被移動,而不是「變量(標籤)不再可訪問」?是否這樣做使'v0'未定義 - 即編譯器正在保護我訪問一個未定義的變量?編譯器錯誤消息有點令人困惑。例如。 '使用移動值:v0'應該說「使用從v0移出的值」。 'v0移動到這裏是因爲...'應該是'* v0的內容*移到這裏了......「(強調增加了)。 'v0'不是被移動的東西。我的理解是否正確? – Kelvin