Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move of a struct variable is a "move" but new space in memory is allocated and addresses of underlying values are different

I'm trying to understand Rust's move semantics in the case of a struct that contains fields with types that implement the Copy trait. Consider the following struct:

struct Book {
    author: &'static str,
    title: &'static str,
    year: u32,
}

fn main() {
    let bookA = Book {
        author: "Douglas Hofstadter",
        title: "Gödel, Escher, Bach",
        year: 1979,
    };
    
    let addr_bookA: *const Book = &bookA;
    let bookB = bookA; // Move occurs here
    
    // Getting the memory addresses as raw pointers
    
    let addr_bookB: *const Book = &bookB;
    
    println!("Address of bookA: {:p}", addr_bookA);
    println!("Address of bookB: {:p}", addr_bookB);
}

Output:

Address of bookA: 0x7fff20b1a0b0
Address of bookB: 0x7fff20b1a0e0

Given there is a move and bookB takes up the value that was assigned to bookA, I was expecting a shallow copy of the data when bookA is assigned to bookB. However, when I check the memory addresses of these two variables, they are different.

Could someone help clarify the following points?

  1. Why does a move of a struct still result in different memory addresses for the original and the moved-to variables?

  2. Is the data actually copied in this scenario, and if so, why does Rust treat it as a move?

Playground

like image 468
dowjones123 Avatar asked Oct 22 '25 05:10

dowjones123


1 Answers

Is the data actually copied in this scenario, and if so, why does Rust treat it as a move?

Because the only difference between a move and a copy is that with a copy the original can still be used. Semantically, both are memcpy (so byte-copy of the source to the target).

Those copies may be optimised away, but that's independent of the semantics.

Why does a move of a struct still result in different memory addresses for the original and the moved-to variables?

Because LLVM does not optimise away the copy. I will confess that I don't know why, I used to assume LLVM would not see the difference between an SSA version of the same thing but clearly it does and either refuses or can not optimise its stack allocation by removing the copy (just relabelling internally). I've never dived into the reason why that could not happen tho, there might be some metadata which rustc is not setting, or some safety corner case which prevents LLVM from doing it.

like image 153
Masklinn Avatar answered Oct 24 '25 13:10

Masklinn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!