In Rust, do the methods extend
and drain
from Vec and VecDeque copy the contents of the items, or are the items moved in like in a list?
Consider that reserve
reserve has been called prior, and that the Vec/VecDeque already have space for the elements.
Edit: For clarification, what happens, at memory level, with the following code? Are the contents copied from Vec to VecDeque, or is there simply a change in pointers like removing/inserting in a linked list?
let mut a: Vec<i32> = (0..10).collect();
let mut b: VecDeque<i32> = VecDeque::new();
b.reserve(10);
b.extend(a.drain(..));
The data of a
and b
are on fixed locations in memory. Because b
already has enough capacity, a reallocation of b
won't happen.
The data itself, though, will be memcopied from a
to b
, and a
will be marked empty afterwards.
To demonstrate, here is a little program that shows the inner state of a Vec
during such a process:
use std::fmt::Debug;
macro_rules! dbg_vec {
($v: ident) => {
dbg_vec_impl(stringify!($v), &$v);
};
}
fn dbg_vec_impl<T: Debug>(name: &str, v: &Vec<T>) {
println!(
"Vec '{}': ({:p}, {}, {})",
name,
v.as_ptr(),
v.len(),
v.capacity()
);
println!(" Real content: {:?}", v);
unsafe {
println!(
" Memory content: {:?}",
std::slice::from_raw_parts(v.as_ptr(), v.capacity())
)
};
}
fn main() {
let mut a: Vec<i32> = (0..10).collect();
let mut b: Vec<i32> = Vec::new();
dbg_vec!(a);
dbg_vec!(b);
b.reserve(10);
println!("\nb.reserve(10);\n");
dbg_vec!(a);
dbg_vec!(b);
b.extend(a.drain(..));
println!("\nb.extend(a.drain(..))\n");
dbg_vec!(a);
dbg_vec!(b);
a.shrink_to_fit();
b.shrink_to_fit();
println!("\nshrink_to_fit()\n");
dbg_vec!(a);
dbg_vec!(b);
}
Vec 'a': (0x1e932d5deb0, 10, 10)
Real content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Vec 'b': (0x4, 0, 0)
Real content: []
Memory content: []
b.reserve(10);
Vec 'a': (0x1e932d5deb0, 10, 10)
Real content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Vec 'b': (0x1e932d5dd60, 0, 10)
Real content: []
Memory content: [5439557, 5505099, 5242959, 7667773, 6553710, 6684773, 7209065, 6553701, 5177344, 3997779]
b.extend(a.drain(..))
Vec 'a': (0x1e932d5deb0, 0, 10)
Real content: []
Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Vec 'b': (0x1e932d5dd60, 10, 10)
Real content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
shrink_to_fit()
Vec 'a': (0x4, 0, 0)
Real content: []
Memory content: []
Vec 'b': (0x1e932d5dd60, 10, 10)
Real content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]