Vec<T> in Depth

clear()

The .clear() method removes all elements from a Vec<T> in place (equivalent to v.truncate(0)), setting v.len() to 0 while retaining the entire allocated heap capacity.

Signature and Memory Behavior

pub fn clear(&mut self)

When v.clear() is called:

  1. If T implements Drop (or contains fields that implement Drop, such as String), .clear() runs the destructor of each element v[0..len] in order. If T has no destructor (std::mem::needs_drop::<T>() == false, such as i32 or u8), .clear() simply sets self.len = 0 in a single CPU instruction.
  2. No heap deallocation occurs: v.capacity() and v.as_ptr() remain unchanged so subsequent .push() or .extend() calls reuse the existing allocation without calling the global allocator.
Before `v.clear()`:
Stack: (ptr = 0x1000, len = 3, cap = 4)  ──> Heap: [ "a", "b", "c" | -- ]

After `v.clear()` ("a", "b", "c" dropped; heap block kept!):
Stack: (ptr = 0x1000, len = 0, cap = 4)  ──> Heap: [  -- , -- , -- , -- ]

Reusing a Scratch Vec<T> Across Loop Iterations

Allocating a Vec<T> inside a hot loop allocates and frees heap memory on every iteration. Hoisting let mut buf = Vec::new(); outside the loop and calling buf.clear() at the start of each iteration reuses the same heap buffer across the entire loop:

fn main() {
    let mut scratch: Vec<u32> = Vec::with_capacity(8);
    let initial_ptr = scratch.as_ptr();

    for round in 1..=3 {
        scratch.clear(); // Resets len to 0, keeps capacity = 8
        scratch.extend((1..=4).map(|x| x * round));
        println!(
            "Round {round}: {scratch:?} (len={}, cap={}, same_ptr={})",
            scratch.len(),
            scratch.capacity(),
            scratch.as_ptr() == initial_ptr
        );
    }
}
Round 1: [1, 2, 3, 4] (len=4, cap=8, same_ptr=true)
Round 2: [2, 4, 6, 8] (len=4, cap=8, same_ptr=true)
Round 3: [3, 6, 9, 12] (len=4, cap=8, same_ptr=true)

Releasing Memory When a Cleared Vector Will Not Be Reused

If you want to empty a Vec<T> and immediately return its heap buffer to the allocator:

  • Either call v.clear(); v.shrink_to_fit();, or
  • Assign a fresh empty vector: v = Vec::new(); (which drops the old Vec<T> and its heap allocation immediately).