Does rust copy data in reality even if passing by reference to a function

fn main() {
    let vec0 = vec![0; 1000000000];
    println!("my_number memory location {:p}", &vec0);
    println!("my_number memory location {:p}", &vec0);
    fill_vec(&vec0);
    println!("my_number memory location {:p}", &vec0);
    let mut vec1 = fill_vec(&vec0);
    

    vec1.push(88);
    println!("my_number memory location {:p} after the push", &vec0);
  
    fill_vec(&vec0);
}

fn fill_vec(vec: &Vec<i32>) -> Vec<i32> {
    println!("my_number memory location inside the function {:p}", &vec);

    vec.to_vec()
}

Output after running the program

my_number memory location 0x29936ff8f0
my_number memory location 0x29936ff8f0
my_number memory location inside the function 0x29936ff968 
my_number memory location 0x29936ff8f0
my_number memory location inside the function 0x29936ff968
my_number memory location 0x29936ff8f0 after the push
my_number memory location inside the function 0x29936ff908

Even when we passed the vector by reference to function the compiler changed the memory address.
Is it some sort of optimization ? If so how does copying optimize the final program?

I don't have any practical problem I need to solve, I am just curious.

Inside the function, &vec will be a &&Vec<i32> and you're printing the address that that is pointing to, i. e. the address where the refetence lives that you passed to the function.

If you change it to

    println!("my_number memory location inside the function {:p}", vec);

it will print the same address everywhere.


Also note that this approach, too, will not print the memory address of the vector's data but just the address of the Vec<i32> struct that consists of the data pointer and length+capacity information. Since the struct doesn't move, it's location will stay the same, but even if it was moved that would not need to imply any copying of the actual vec data has occurred.

2 Likes

How would we find location of actual data in the vector?
Is println!("vector data location {:p}", &vec[0]); correct.
Is all vector data stored at same place in memory .

One option is to print vec.as_ptr().

Using {:p} with &vec[0] or &vec[..] or vec.as_slice() would be an option, too.

All of the options listed above should work equally well regardless of whether vec is a Vec<T> or a &Vec<T>, and even a &[T] would work.

Taking a reference to the first element of course would panic for an empty vector.

2 Likes

Vec::as_ptr can probably help, if only for learning purposes.

Not sure what you're asking here. If you mean "is the vector data stored continuously?", then, yes, it's guaranteed:

If a Vec has allocated memory, then the memory it points to is on the heap (as defined by the allocator Rust is configured to use by default), and its pointer points to len initialized, contiguous elements in order (what you would see if you coerced it to a slice), followed by capacity - len logically uninitialized, contiguous elements.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.