I am a bit confused about how to transfer ownership without the overhead of actual data copy. I have the following code. I am referring to underlying data copy by OS as memcopy.
fn main() {
let v1 = Vec::from([1; 1024]);
take_ownership_but_memcopies(v1);
let v2 = Vec::from([2; 1024]);
dont_memecopy_but_dont_take_ownership(&v2);
let v3 = Vec::from([3; 1024]);
take_ownership_dont_memcopy(???);
}
// Moves but memcopies all elements
fn take_ownership_but_memcopies(my_vec1: Vec<i32>) {
println!("{:?}", my_vec1);
}
// Doesn't memcopy but doesn't take ownership
fn dont_memecopy_but_dont_take_ownership(my_vec2: &Vec<i32>) {
println!("{:?}", my_vec2);
}
// Take ownership without the overhead of memcopy
fn take_ownership_dont_memcopy(myvec3: ???) {
println!("{:?}", my_vec3);
}
As i understand, if i use reference like v2, i don't get the ownership. If i use it like v1, there could be a memcopy.
How should i need to transfer v3 to guarantee that there is no underlying memcopy by OS?
Your understanding of what happens when you move a Vec
is incorrect - it does not copy every element within the Vec
!
To understand why, we need to take a step back and look at how a Vec
is represented internally:
// This is slightly simplified, look at the source for more details!
struct Vec<T> {
pointer: *mut T, // pointer to the data (on the heap)
capacity: usize, // the current capacity of the Vec
len: usize, // the current number of elements in the Vec
}
While the Vec
conceptually 'owns' the elements, they are not stored within the Vec
struct - it only holds a pointer to that data. So when you move a Vec
, it is only the pointer (plus the capacity and length) that gets copied.
If you are attempting to avoid copying altogether, as opposed to avoiding copying the contents of the Vec
, that isn't really possible - in the semantics of the compiler, a move is a copy (just one that prevents you from using the old data afterwards). However, the compiler can and will optimize trivial copies into something more efficient.