Skip to content

Vec::new

Vec methods · Collections

Level: reference · for working programmers

One line: An empty vector that has not allocated anything yet.

pub const fn new() -> Vec<T>

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

Vec::new() allocates nothing. It writes three numbers — a dangling pointer, length 0, capacity 0 — and the first push is what asks the allocator for a buffer. Creating one you may never fill is therefore free, which is why this is the default constructor rather than with_capacity.

It is the one Vec constructor usable in a const or static initialiser: static EMPTY: Vec<u8> = Vec::new(); compiles.

The type has to come from somewhere. Vec::new() alone is Vec<_>, and the compiler needs an annotation, a later push, or a typed binding to settle it — otherwise error[E0282]: type annotations needed forVec<_>``.

vec![] and Default::default() produce exactly the same thing — but a non-empty vec![…] does not behave like new plus pushes: it allocates its length exactly, so vec![1, 2, 3] has capacity 3 where three pushes give 4. See capacity. Vec::new() followed immediately by pushes is what clippy::vec_init_then_push (warn by default) rewrites into a vec![] literal.

A Vec of a zero-sized type never allocates whatever you push into it, and reports usize::MAX capacity: there is no buffer, so there is nothing to exhaust.

Example

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

fn main() {
    // `new` allocates nothing. An empty Vec is three numbers and no heap.
    let v: Vec<i32> = Vec::new();
    println!("len {} cap {} empty {}", v.len(), v.capacity(), v.is_empty());

    // The type has to come from somewhere: an annotation, or later use.
    let mut inferred = Vec::new();
    inferred.push("Ada");          // now it is a Vec<&str>
    println!("{inferred:?}");

    // Three spellings of the same empty vector.
    let a: Vec<u8> = Vec::new();
    let b: Vec<u8> = vec![];
    let c: Vec<u8> = Default::default();
    println!("{} {}", a == b, b == c);

    // The first push is what allocates, and it jumps straight past 1.
    let mut v: Vec<u32> = Vec::new();
    println!("before push: cap {}", v.capacity());
    v.push(1);
    println!("after push:  cap {}", v.capacity());

    // A Vec of a zero-sized type never allocates at all.
    let mut zst: Vec<()> = Vec::new();
    for _ in 0..1000 { zst.push(()); }
    println!("1000 units: len {} cap is usize::MAX {}", zst.len(), zst.capacity() == usize::MAX);
}

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

len 0 cap 0 empty true
["Ada"]
true true
before push: cap 0
after push:  cap 4
1000 units: len 1000 cap is usize::MAX true

See also

Vec::new in the standard library ↗