Vec<T> in Depth

Creating Vectors

Vec<T> provides multiple constructors and conversion traits for creating empty vectors, pre-allocated vectors, and vectors initialized from arrays, slices, or iterators.

Summary of Vec<T> Construction Methods

Constructor / Expression Heap Allocation Behavior Required Trait on T
Vec::new() / Vec::default() Zero heap allocation (capacity == 0, const fn for Vec::new()) None (T: Sized)
Vec::with_capacity(n) Allocates uninitialized space for n elements (len == 0, capacity == n) None (T: Sized)
vec![a, b, c] Allocates exact capacity (3) and moves elements in None (T: Sized)
vec![val; n] Allocates capacity n and clones val into each slot T: Clone
Vec::from([a, b, c]) Moves elements from fixed-size array [T; N] into a heap buffer None (T: Sized)
slice.to_vec() / Vec::from(slice) Allocates slice.len() and clones each element (memcpy for Copy) T: Clone
iter.collect::<Vec<T>>() Pre-allocates size_hint().0 and collects iterator items None (T: Sized)

Creating Empty and Pre-Allocated Vectors

Because Vec::new() is a const fn that does not allocate heap memory until the first element is pushed, an empty Vec<T> can be stored in const or static items and costs nothing to construct:

static EMPTY_NAMES: Vec<String> = Vec::new();

fn main() {
    // 1. Empty vector with explicit type annotation on binding:
    let mut numbers: Vec<i32> = Vec::new();
    println!("Vec::new(): len={}, cap={}", numbers.len(), numbers.capacity());
    numbers.push(10);

    // 2. Pre-allocated vector via turbofish `Vec::<T>::with_capacity`:
    let preallocated = Vec::<u64>::with_capacity(32);
    println!(
        "with_capacity(32): len={}, cap={}",
        preallocated.len(),
        preallocated.capacity()
    );
    println!("Static empty len: {}", EMPTY_NAMES.len());
}
Vec::new(): len=0, cap=0
with_capacity(32): len=0, cap=32
Static empty len: 0

Creating Vectors from Arrays, Slices, and Iterators

fn main() {
    // 1. From a fixed-size array by value (moves Non-Copy Strings without cloning):
    let from_array = Vec::from([String::from("alpha"), String::from("beta")]);

    // 2. From a borrowed slice (clones elements via `to_vec()`):
    let raw_slice: &[i32] = &[10, 20, 30];
    let from_slice: Vec<i32> = raw_slice.to_vec();

    // 3. From a range or iterator pipeline via `.collect()`:
    let evens: Vec<i32> = (1..=5).map(|x| x * 2).collect();

    println!("from_array: {from_array:?}");
    println!("from_slice: {from_slice:?}");
    println!("evens:      {evens:?}");
}
from_array: ["alpha", "beta"]
from_slice: [10, 20, 30]
evens:      [2, 4, 6, 8, 10]