fn main() {
let x = 5;
let y = &x;
println!("value of y is {}",y);
println!("value of *y is {}",*y);
}
In this example, y = &x means that y gets the memory address of x , right? And *y means that through the memory address of x , we get the value of x , which is 5, right?
Then why are the results of the two println! both 5?
Or can someone explain &x and *y more clearly,
or say that &x and *y should be seen as a whole, not understood * or & separately?
Because references have a transitive Display impl that simply forwards to the pointed value. If you want to print a reference as a memory address, use the {:p} specifier in the format string instead.
y is a reference to x. While under the hood a reference is implemented as a pointer, semantically it should act like the value it points to. For this reason the Display trait, which is the one used to print values with println, is implemented for references by forwarding to the implementation of the pointed value.
That's not quite as generally true as you seem to make it appear. The distinction between references and non-reference values (and in general, explicitness with regards to indirection) is a very important one in this language.
Sometimes it makes sense to simply delegate references' behavior to the referenced value, often for no more than reasons of convenience, in which case explicit impls are provided – this is exactly the story of Display. But if a reference should always just act like the pointed value, then this behavior would probably automatic and/or opt-out (which, thankfully, is not how it works).
There's nothing weird in that. It's exactly the same phenomenon. There's a blanket impl<T: Display> Display for &T, but there's no such transitive impl for AddAssign on &mut T. (Probably in order not to confuse people who try to perform pointer arithmetic on references.)
By the way, Deref is not implemented for i32. Deref is usually only implemented for pointer-like types (including plain references) and "smart pointers" in the broader sense (e.g. Vec and String).
*foo is a place expression which is evident in things like *foo = 1; or &*boxed_value. They often immediately get turned into a value, which is why it might look like reading values from a location behind a reference.