References and move vs. copy

Solution 1:

fn main() {
    let s1 = String::from("Hello");
    let s2 = &s1;
    do_something(s2);
    println!("{}", s2);
}

This works because references are Copy. s2 is copied, not moved, and can continue to be used after the call to do_something.


Is the above the same as this?

fn main() {
    let a = 5;
    let b = &a;
    do_something(b);
    println!("{}", b);
}

Yes, it is. It doesn't matter if a or s1 are Copy, only that b or s2 are.


I guess my question is, are they Copy because they are always pointers to stack-allocated data?

All shared references are Copy because of the blanket implementation:

impl<'_, T> Copy for &'_ T
where
    T: ?Sized, 

It doesn't matter where the references point, stack or heap or .data section or anywhere else. References are small word-sized values and it's convenient and efficient to copy them, so Rust makes them Copy.

That's the usual metric: Is copying efficient? Strings aren't Copy because cloning them is an expensive O(n) operation. &strs, being references, are Copy because copying pointers is cheap.

(It's not the only metric, of course. Some types are not Copy because they are logically unique. For example, Box is also just a pointer, but it's an owned type, not a shared reference.)