Cartucho
Cartucho

Reputation: 157

References and move vs. copy

I'm reading through chapter 4 of the Rust book, coming from a Python background.

What confuses me a bit is that this doesn't compile:

fn do_something(s3: String) {
    println!("{}", s3);
}

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

(as it shouldn't, because s is moved in the function call), but this does:

fn do_something(s3: &String) {
    println!("{}", s3);
}

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

if I understand correctly, this is because s1 is already a pointer, so s2 is a pointer (well, a refrence) to a (stack-allocated) pointer. Therefore, s2 is copied in the function call and not moved. Is this so? Is the above the same as this?

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

Upvotes: 5

Views: 4073

Answers (1)

John Kugelman
John Kugelman

Reputation: 361575

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.)

Upvotes: 5

Related Questions