Vec<T> in Depth
append() and extend()
Vec<T> provides three bulk-appending methods—.append(&mut other), .extend(iter), and .extend_from_slice(slice)—that add multiple elements to the back of a vector while reserving the required capacity upfront.
Comparison of Bulk-Appending Methods
| Method | Signature | What Happens to the Source? | Trait Bounds |
|---|---|---|---|
v.append(&mut other) |
fn append(&mut self, other: &mut Vec<T>) |
Moves all elements out of other, leaving other empty (other.len() == 0) while keeping other's heap capacity |
None (T: Sized) |
v.extend(iter) |
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) |
Consumes iter (Vec<T>, array, range, or adapter chain) and appends each item |
None (or T: Copy when extending from Iterator<Item = &T>) |
v.extend_from_slice(s) |
fn extend_from_slice(&mut self, other: &[T]) |
Borrows other: &[T] and clones each element onto self (memcpy for Copy types) |
T: Clone |
v.extend_from_within(r) |
fn extend_from_within<R: RangeBounds<usize>>(&mut self, src: R) |
Clones a subrange of self and appends it to the end of self |
T: Clone |
v.append(&mut other):
Before: v = [1, 2], other = [3, 4] (cap = 4)
After: v = [1, 2, 3, 4], other = [] (cap = 4, reusable!)
Moving Elements Between Vectors with append()
Because v.append(&mut other) transfers elements in a single contiguous ptr::copy_nonoverlapping block and sets other.len = 0 without dropping other's allocation, it is ideal when other is a reusable scratch buffer in a loop:
fn main() {
let mut main_batch = vec![String::from("job-1"), String::from("job-2")];
let mut worker_batch = vec![String::from("job-3"), String::from("job-4")];
main_batch.append(&mut worker_batch);
println!("main_batch: {main_batch:?}");
println!(
"worker_batch: {worker_batch:?} (len={}, cap={})",
worker_batch.len(),
worker_batch.capacity()
);
}
main_batch: ["job-1", "job-2", "job-3", "job-4"]
worker_batch: [] (len=0, cap=2)
Appending Iterators and Slices with extend() and extend_from_slice()
fn main() {
let mut nums = vec![1, 2];
// 1. Append from any IntoIterator (such as a range or mapped iterator):
nums.extend(3..=5);
// 2. Append from a borrowed slice `&[i32]`:
let tail = [6, 7, 8];
nums.extend_from_slice(&tail);
// 3. Duplicate the first 3 elements (`0..3`) onto the end of `nums`:
nums.extend_from_within(0..3);
println!("nums: {nums:?}");
}
nums: [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3]