2016-11-27 140 views
2

考慮以下(啞)程序:在聲明for循環變量時,mut&mut會做什麼嗎?

fn main() { 
    let mut array = &mut [1u8, 2u8, 3u8]; 
    for &mut value in array { 
    } 
} 

它編譯和運行好(儘管發出警告未使用的變量/不必要的可變性,如預期)。但&mutfor聲明中做什麼?

它似乎沒有給你一個可變的引用到數組,因爲試圖分配value = 0;導致錯誤:

error[E0384]: re-assignment of immutable variable `value` 

&mut這裏無操作呢?

回答

7

所以這裏有一些不同的事情發生在這裏。首先,這裏是答案:

fn main() { 
    let mut array = [1u8, 2u8, 3u8]; 
    for value in &mut array { 
     *value = 0; 
    } 
} 

所以。你哪裏錯了?讓我們來看看什麼是value,像這樣:

for &mut value in array { 
    let() = value; 
} 

這給出了這樣的錯誤:

= note: expected type `u8` 
    = note: found type `()` 

所以在這裏,valueu8。但爲什麼?好吧,讓我們試試這個:

for value in array { 
    let() = value; 
} 

這給:

= note: expected type `&mut u8` 
    = note: found type `()` 

所以,value這裏是一個&mut u8,參考到數組。所以說for &mut value,我們說:「嘿,這將是一個可變的指針u8。我們希望value到是已指着u8值,這是因爲&mut value模式,結合。針對&mut T並結合valueT

所以,我們刪除了&mut,因爲我們不希望值的副本,我們想用它來修改什麼指着所以看起來像這樣:

fn main() { 
    let mut array = &mut [1u8, 2u8, 3u8]; 
    for value in array { 
     *value = 0; 
    } 
} 

這個......編譯!我們完了嗎?好吧,讓我們嘗試打印出來array,只是要確定:

fn main() { 
    let mut array = &mut [1u8, 2u8, 3u8]; 
    for value in array { 
     *value = 0; 
    } 

    println!("{:?}", array); 
} 

這無法編譯:

error[E0382]: use of moved value: `array` 
--> <anon>:7:22 
    | 
3 |  for value in array { 
    |     ----- value moved here 

我們通過遍歷破壞array。爲什麼?那麼,當你像這樣循環訪問一個數組時,你說你想循環所有者。但這是而不是其實我們想要的;我們想通過可變引用來循環。

陣列有一個方法來幫助這個:

fn main() { 
    let mut array = &mut [1u8, 2u8, 3u8]; 
    for value in array.iter_mut() { 
     *value = 0; 
    } 

    println!("{:?}", array); 
} 

iter_mut&mut T而不是T迭代。所以這個工作!

最後一兩件事,但:

let mut array = &mut [1u8, 2u8, 3u8]; 

這是說array&mut [u8; 3],那就是,一個可變引用數組,而不是數組本身。這可能不是你真正想要的,並且它不是我們的代碼所必需的。因此,我們可以刪除&mut位:

let mut array = [1u8, 2u8, 3u8]; 

而現在你在我們的第一個代碼示例。

希望這會有所幫助!

+1

這是一個*夢幻般的*答案。謝謝你的詳細解釋和所有的例子! – Cornstalks

1

Is &mut here a no-op then?

不,它是模式的一部分。 Print the type of value

fn main() { 
    let mut array = &mut [1u8, 2u8, 3u8]; 

    for &mut value in array { 
     let() = value; 
     // expected type `u8` 
    } 

    for value in array { 
     let() = value; 
     // expected type `&mut u8` 
    } 
} 
+0

將'for'-loop拖拽到它的'loop {match ... {}}'等價物中並考慮模式匹配,從而使結果變得有意義。謝謝!早些時候,我嘗試了打印類型(使用'let()= value;'trick),但感到困惑的是它是'u8',但那是因爲我期待'&mut value'聲明一個可變引用而不是作爲模式。感謝這個簡潔的例子和解釋! – Cornstalks

相關問題