C.W.K.
Stream
Lesson 01 of 06 · published

Vec — The Growable Array

~10 min · collections, vec, heap

Level 0Rust Curious
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

The Collections track is where everything you've learned — ownership, borrowing, generics, traits — pays off in the data structures you'll use every day. We start with the most common: Vec<T>, the growable array.

A growable, heap-allocated sequence

A Vec<T> holds any number of values of one type T, growing as you push. Unlike an array [T; N] with its compile-time-fixed length, a vector lives on the heap and grows at runtime. It's the default 'I need a list of things' type in Rust.

Push, index, iterate

You push to add, index with [i] (panics out of bounds) or get(i) (returns an Option, no panic), and iterate with for x in &v. The ownership rules apply: iterating with &v borrows, &mut v borrows mutably, v consumes. The borrow checker won't let you push to a vector while iterating it — the iterator-invalidation bug, eliminated.

get() over [] when the index might be out of range. v[i] panics if i is too big; v.get(i) returns Option<&T> so you handle the missing case safely. Use indexing when you've already proven the bound; use get when the index comes from outside.

vec! and capacity

The vec![1, 2, 3] macro builds one inline. Under the hood a Vec has a length and a capacity; pushing past capacity reallocates to a bigger buffer (amortized O(1)). When you know the size ahead, Vec::with_capacity(n) pre-allocates and skips the regrowth.

Code

Push, safe get(), and iterate·rust
fn main() {
    let mut scores = vec![90, 85, 100];
    scores.push(70);              // grow at runtime

    // Safe access: get() returns Option, no panic
    if let Some(first) = scores.get(0) {
        println!("first: {first}");
    }
    println!("missing: {:?}", scores.get(99)); // None

    // Iterate by reference (borrow, don't consume)
    let total: i32 = scores.iter().sum();
    println!("total: {total}");
}

External links

Exercise

Build a Vec<i32>, push several values, then access one index with [] and another (out of range) with .get(). Observe that [] panics on a bad index while .get() returns None. Then iterate with .iter() and sum the values. Why does the borrow checker stop you from pushing inside a for x in &v loop?
Hint
Pushing might reallocate the vector's buffer, invalidating the reference the loop holds. The borrow checker refuses it at compile time — the classic iterator-invalidation crash, made impossible.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.