Skip to content

Vec::pop

Vec methods · Collections

Level: reference · for working programmers

One line: Take the last element off, as an Option.

pub fn pop(&mut self) -> Option<T>

Stable since 1.0.0.

None when the vector is empty — the type makes you say what happens then, which is the difference from a language where popping an empty list is a runtime error you find in production.

O(1), and it does not shrink the buffer: emptying a vector with pop leaves the whole allocation in place, ready to be refilled.

The element is moved out, not cloned, so pop works on types that are not Clone.

Vec plus push/pop is Rust's stack. There is no separate Stack type, and none is needed. while let Some(x) = v.pop() is the drain-it-all idiom — though clippy::manual_while_let_some (warn by default) will point you here from the while !v.is_empty() version.

pop_if is the conditional form, which avoids looking at the last element twice.

Example

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

fn main() {
    let mut v = vec![1, 2, 3];
    println!("{:?} {:?} {:?} {:?}", v.pop(), v.pop(), v.pop(), v.pop());
    println!("empty now: {v:?}");

    // Option is the whole point: an empty Vec has nothing to give, and the
    // type makes you say what happens then.
    let mut stack = vec!["a", "b"];
    while let Some(top) = stack.pop() { println!("popped {top}"); }

    // pop is O(1) and does not shrink the buffer.
    let mut v = vec![1u8; 100];
    let cap = v.capacity();
    for _ in 0..100 { v.pop(); }
    println!("len {} cap unchanged {}", v.len(), v.capacity() == cap);

    // Vec + push/pop is Rust's stack. There is no separate Stack type.
    let mut stack: Vec<char> = Vec::new();
    let mut balanced = true;
    for c in "([{}])".chars() {
        match c {
            '(' | '[' | '{' => stack.push(c),
            ')' => balanced &= stack.pop() == Some('('),
            ']' => balanced &= stack.pop() == Some('['),
            '}' => balanced &= stack.pop() == Some('{'),
            _ => {}
        }
    }
    println!("balanced: {} leftovers: {:?}", balanced && stack.is_empty(), stack);

    // The value is moved out, not cloned — pop works on non-Clone types.
    let mut owners = vec![String::from("only copy")];
    let taken = owners.pop().unwrap();
    println!("{taken:?} and the vec is {owners:?}");
}

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

Some(3) Some(2) Some(1) None
empty now: []
popped b
popped a
len 0 cap unchanged true
balanced: true leftovers: []
"only copy" and the vec is []

See also

Vec::pop in the standard library ↗