Skip to content

Vec::capacity

Vec methods · Collections

Level: reference · for working programmers

One line: How many elements fit before the next reallocation — not how many are there.

pub const fn capacity(&self) -> usize

Stable since 1.0.0. Callable in a const context since 1.87.0.

len is what is in the vector; capacity is what the buffer holds. capacity() >= len() always, and the gap between them is spare_capacity_mut.

The first non-zero capacity depends on the element size, not on the count. std picks 8 for one-byte elements, 4 for anything up to 1 KiB, and 1 above that — so a Vec<u8> jumps to 8 on its first push while a Vec<u32> jumps to 4 and a Vec<[u8; 2048]> jumps to 1. After that it doubles.

vec![…] does not follow that rule. vec![1, 2, 3].capacity() is 3, not 4: the macro builds a boxed array and converts it, so the capacity is exact rather than rounded up to a growth step. Vec::new() plus the same three pushes gives 4. vec![0u8; n] is exact too, even when n is a run-time value. So the macro behaves like with_capacity, not like new — which is worth knowing before you compare two capacities and conclude something about growth.

The growth sequence is this standard library's choice, not a language promise. Two things are promised: capacity() >= len(), and a reservation gives you at least what you asked for. Write against those, not against the doubling.

Capacity never shrinks on its own. clear, truncate, pop, drain and retain all leave the buffer at full size deliberately, because the usual next thing is refilling it. shrink_to_fit is the only way to hand memory back.

For a zero-sized type the capacity is usize::MAX.

Example

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

fn main() {
    let mut v: Vec<u32> = Vec::with_capacity(10);
    v.push(1);
    println!("len {} capacity {}", v.len(), v.capacity());

    // The first non-zero capacity depends on the element SIZE:
    // 8 for one-byte elements, 4 up to 1 KiB, 1 above that.
    let mut a: Vec<u8> = Vec::new();          a.push(0);
    let mut b: Vec<u32> = Vec::new();         b.push(0);
    let mut c: Vec<[u8; 2048]> = Vec::new();  c.push([0; 2048]);
    println!("first capacity — u8 {} u32 {} [u8; 2048] {}",
             a.capacity(), b.capacity(), c.capacity());

    // After that it doubles.
    let mut v: Vec<u32> = Vec::new();
    let mut seq = vec![];
    for n in 0..20u32 {
        v.push(n);
        if seq.last() != Some(&v.capacity()) { seq.push(v.capacity()); }
    }
    println!("capacity sequence: {seq:?}");

    // ...but the vec![] macro does not go through that path at all. It builds
    // a boxed array and converts it, so the capacity is EXACT.
    let n = 3;
    println!("vec![1,2,3] {}   new()+3 pushes {}   vec![0u8; n] {}",
             vec![1, 2, 3].capacity(),
             { let mut v = Vec::new(); v.push(1); v.push(2); v.push(3); v.capacity() },
             vec![0u8; n].capacity());

    // A zero-sized type never allocates, so its capacity is the maximum.
    let z: Vec<()> = Vec::new();
    println!("Vec<()> capacity is usize::MAX: {}", z.capacity() == usize::MAX);

    // Capacity never shrinks on its own. Removing everything keeps the buffer.
    let mut v = vec![0u8; 100];
    v.clear();
    println!("cleared: len {} cap {}", v.len(), v.capacity());
    v.shrink_to_fit();
    println!("shrunk:  len {} cap {}", v.len(), v.capacity());

    // The exact growth sequence is this std's choice, not a language promise.
    // What IS promised: capacity >= len, always, and reserve gives at least
    // what you ask for.
    let mut v: Vec<u16> = Vec::new();
    v.reserve(100);
    println!("capacity >= len: {}  >= reserved: {}",
             v.capacity() >= v.len(), v.capacity() >= 100);
}

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

len 1 capacity 10
first capacity — u8 8 u32 4 [u8; 2048] 1
capacity sequence: [4, 8, 16, 32]
vec![1,2,3] 3   new()+3 pushes 4   vec![0u8; n] 3
Vec<()> capacity is usize::MAX: true
cleared: len 0 cap 100
shrunk:  len 0 cap 0
capacity >= len: true  >= reserved: true

See also

Vec::capacity in the standard library ↗