2016-11-27 96 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

相关问题