17

What is the difference between

let y = &mut 5;
*y += 1;
let x = *y + 1;

and

let mut y = 5;
y += 1;
let x = y + 1;

They return the same result via println!, but I can't decide which one is preferable.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
tbmale
  • 185
  • 1
  • 1
  • 5

1 Answers1

33

Given your simple example of binding a variable to one or the other, then calling println! locally, there really isn't much difference in the result (as you've noted).

A mutable value vs a mutable reference becomes more clear when you cross function boundaries. Have a look at this code:

fn main() {
    let mut x = &mut 5;

    do_work(x);

    println!("{}", x);
}

fn do_work(n: &mut u32) {
    *n += 5;
}

What do you think it prints? Here it is on the playground

Now look at this code:

fn main() {
    let mut x = 5;

    do_work(x);

    println!("{}", x);
}

fn do_work(mut n: u32) {
    n += 5;
}

What do you think this prints? Here it is on the playground

The answers are:

The top code block prints 10. The bottom code block prints 5.

Using the mutable reference means you're referencing the place in memory where the variable x is stored. Across function boundaries, you're able to change the value stored in memory there. When the method returns and println! hits.. the value of x is updated.

In this specific example, x is a u32, which implements the Copy trait. When you pass x into the do_work method, a copy of x is made. In the body of the do_work method, n += 5 adds 5 to the copy .. and does not reference the original block of memory at all.

...can't decide which one is preferable.

That depends entirely on use-case. Do you need to reference the original memory when crossing a function boundary? If you have marked your variable as mutable, there is a high chance that you do want to reference the original memory in the hopes of updating it. In that case, you would use a mutable reference. If you're just mutating a variable locally within a function.. then you won't require a reference.

Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138
  • You can remove the `mut` from `let mut` in the first example and it would still work, so I don't think this really answers OP's question. – what the Jun 20 '23 at 23:01