Why do I need `*` to change a value in a vector?

Viewed 241

I am confused by this example.

    let mut numbers: Vec<i32> = vec![1,2,3,4];
    for x in numbers.iter() {
        println!("Number: {}", x);
    }

    // Try to double the values in the vector.
    for x in numbers.iter_mut() {
        *x *= 2;
    }

when I tried x *= 2;, the compiler complains cannot use '*=' on type '&mut i32' but isn't x just a mut i32? why it is a &mut i32? if it is a &mut i32 why I dont need to print it as println!("Number: {}", *x)?

2 Answers

but isn't x just a mut i32?

Nope, iter_mut returns an IterMut item, which implements Iterator<Item=&mut T>, so you are actually getting an &mut i32

why don't I need to print it as println!("Number: {}", *x)?

Because Display is implemented for &mut T by delegating to T, so println!("{}", x) and println!("{}", *x) print the same thing. For more information, see how println! works

if x is a &mut i32 why don't I need to print it as println!("Number: {}", *x)?

Good question!

The answer is because, when you use the println!() macro, references are automatically dereferenced. So the following lines are functionally equivalent:

println!("Number: {}", x);  // x is a reference
println!("Number: {}", *x);

In fact, all these lines (the ones after the declaration) are equivalent, too:

let x = 5;
println!("{}", x);   // prints: 5
println!("{}", &x);   // prints: 5
println!("{}", &&x);   // prints: 5
println!("{}", &&&x);   // prints: 5
println!("{}", &&&&x);   // prints: 5
println!("{}", &&&&&x);   // prints: 5
println!("{}", &&&&&&x);   // prints: 5

So it doesn't matter how many times I reference a reference of a reference, because when I use the println!() macro all my references will be glady dereferenced for me.

This is convenient behavior when using println!(), but it can cause some confusion if you don't realize you're using a reference.

EDIT: Changed wording so that it no longer explicitly says that it's the println!() macro that is doing the dereferencing behavior.

Related