Skip to content

Vec::reserve

Vec methods · Collections

Level: reference · for working programmers

One line: Make room for additional more elements on top of the current length.

pub fn reserve(&mut self, additional: usize)

Stable since 1.0.0.

The argument is additional elements beyond len(), not a target capacity. v.reserve(10) on a vector of length 3 guarantees room for 13. Reading it as "make the capacity 10" is the standard mistake, and on a non-empty vector it under-reserves.

If there is already room it does nothing. Otherwise it reallocates once, and it is allowed to over-allocate deliberately — that speculative slack is what keeps repeated small reservations amortised rather than quadratic. reserve_exact is the version that does not.

Capacity is counted in elements, so reserve(10) on a Vec<u64> asks the allocator for 80 bytes.

You need it less often than it looks: extend_from_slice, collect and extend from an iterator with a known length all reserve once for the whole batch. The case that genuinely wants it is a loop of pushes whose count you can compute beforehand but which no single call can see.

Panics if the new capacity overflows usize or exceeds isize::MAX bytes. try_reserve returns Err instead.

Example

vec_reserve.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    // "additional" is on top of the CURRENT LENGTH, not the current capacity.
    let mut v = vec![1, 2, 3];
    v.reserve(10);
    println!("len {} capacity at least 13: {}", v.len(), v.capacity() >= 13);

    // If there is already room, it does nothing.
    let mut v: Vec<u8> = Vec::with_capacity(100);
    let before = v.capacity();
    v.reserve(10);
    println!("already had room, unchanged: {}", v.capacity() == before);

    // It may over-allocate deliberately, so repeated small reserves stay
    // amortised rather than reallocating every time.
    let mut v: Vec<u32> = Vec::new();
    v.reserve(1);
    println!("reserve(1) on an empty Vec<u32> gave capacity {}", v.capacity());

    // The usual use: you know the size just before you fill it.
    let words = ["alpha", "beta", "gamma"];
    let count = |reserve: bool| {
        let mut out: Vec<char> = Vec::new();
        if reserve { out.reserve(words.iter().map(|w| w.len()).sum()); }
        let mut reallocs = 0;
        for w in words {
            for c in w.chars() {
                let before = out.capacity();
                out.push(c);
                if out.capacity() != before { reallocs += 1; }
            }
        }
        (out.len(), reallocs)
    };
    println!("with reserve:    {:?} (len, reallocations)", count(true));
    println!("without reserve: {:?}", count(false));

    // extend() from an iterator with a known length already reserves for you,
    // which is why this is rarely needed with collect() or extend_from_slice().
    let mut v: Vec<u8> = Vec::new();
    v.extend_from_slice(&[0; 50]);
    println!("extend_from_slice reserved once: len {} cap {}", v.len(), v.capacity());

    // Capacity is measured in ELEMENTS. Reserving 10 for a Vec<u64> asks the
    // allocator for 80 bytes.
    let mut v: Vec<u64> = Vec::new();
    v.reserve(10);
    println!("10 u64 slots = {} bytes of buffer", v.capacity() * size_of::<u64>());
}

Verified output of vec_reserve.rs — regenerated by tools/run_examples.py, never hand-typed.

len 3 capacity at least 13: true
already had room, unchanged: true
reserve(1) on an empty Vec<u32> gave capacity 4
with reserve:    (14, 0) (len, reallocations)
without reserve: (14, 3)
extend_from_slice reserved once: len 50 cap 50
10 u64 slots = 80 bytes of buffer

See also

Vec::reserve in the standard library ↗