Does &mut do anything when declaring a for loop variable?

前提是你 提交于 2021-01-27 17:41:19

问题


Consider the following (dumb) program:

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

It compiles and runs okay (though warns about unused variables/unnecessary mutability, as expected). But what does &mut do in the for statement?

It doesn't seem to give you a mutable reference into the array, since trying to assign value = 0; results in the error:

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

Is &mut here a no-op then?


回答1:


So there's a few different things that's going on here. First, here's the answer:

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

So. Where did you go wrong? Let's look at what value is, like this:

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

This gives this error:

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

So here, value is a u8. But why? Well, let's try this one:

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

This gives:

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

So, value here is an &mut u8, a reference into the array. So by saying for &mut value, we're saying "hey, this is going to be a mutable pointer to a u8. We'd like value to be the u8 value that's pointed at. This is because &mut value is a pattern, which binds against a &mut T and binds value to the T.

So, we remove the &mut, since we don't want a copy of the value, we want to use it to modify what's pointed to. So that looks like this:

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

This... compiles! Are we done? Well, let's try to print out array, just to be sure:

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

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

This fails to compile:

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

We've destroyed array by iterating. Why's that? Well, when you loop over an array like this, you're saying you want to loop by owner. But that's not actually what we want; we want to loop by mutable reference.

Arrays have a method to help with this:

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

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

iter_mut will iterate by &mut T rather than by T. So this works!

One last thing, though:

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

This says that array is a &mut [u8; 3], that is, a mutable reference to an array, not an array itself. This probably isn't what you actually want, and it's not neccesary with our code. So we can remove the &mut bit:

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

And now you're at our first code sample.

Hope this helps!




回答2:


Is &mut here a no-op then?

No, it's part of a pattern. 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`
    }
}


来源:https://stackoverflow.com/questions/40834969/does-mut-do-anything-when-declaring-a-for-loop-variable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!