Let's try the following code, which would work in other programming languages:
let p1 = Point { x: 1, y: 2 }; let p2 = p1; println!("{}", p1.x);
We can see that Rust doesn't accept this. It gives the following error:
error[E0382]: use of moved value: `p1.x` --> src/main.rs:4:20 | 3 | let p2 = p1; | -- value moved here 4 | println!("{}", p1.x); | ^^^^ value used here after move | = note: move occurs because `p1` has type `Point`, which does not implement the `Copy` trait
This means that we cannot use a value after it is moved. In Rust, values are moved by default instead of being copied, except in some cases, as we'll see in the next sub-section.
To avoid moving a value, we can take a reference to it by prefixing it with &:
let p1 = Point { x: 1, y: 2 }; let p2 = &p1; println!("{}", p1.x);
This code compiles and, in this case, p2 is a reference to p1, which means that it points to the same memory location. Rust ensures that it is always safe to use a reference, since references are not pointers, they cannot be NULL.
References can also be used in the type of a function parameter. This is a function that prints a point, without moving the value:
fn print_point(point: &Point) { println!("x: {}, y: {}", point.x, point.y); }
We can use it this way:
print_point(&p1); println!("{}", p1.x);
We can still use the point after calling print_point, because we send a reference to the function instead of moving the point into the function.