ProgramGuru

Vectors and changing collections

Vectors and changing collections

A class register changes when students join or leave. Vec is a growable collection of values of one type. Unlike an array, its length can change at runtime. Ownership and borrowing still apply to the vector and the elements it stores.

What you’ll learn

  • Grow a vector and handle uncertain element access.
  • Borrow a collection when later operations still need it.

Vectors and changing collections in action

  1. Initial marks: 70, 80

    Push changes the vector length from two to three.

    Initial marks: 70, 80
  2. Push mark 90

    The borrowed loop prints each value and leaves marks available for the length check.

    Push mark 90
  3. Borrow and print all three

    Index three is outside the collection, so get reports None.

    Borrow and print all three
Push changes the vector length from two to three. The borrowed loop prints each value and leaves marks available for the length check. Index three is outside the collection, so get reports None.

Vectors and changing collections explained

vec! creates a vector. Push adds an element, while get returns a borrowed optional element. Iterating with &marks borrows the vector rather than consuming it. A reference to an element cannot remain in conflicting use across a push because growing storage can relocate elements.

Connect this idea with ownership, moves and cleanup and iterators, closures and transformations.

Work through the Rust program

Save the complete source as main.rs in the Rust environment. No standard input is needed.

Rust 2024 · complete program

fn main() {
  let mut marks = vec![70, 80];
  marks.push(90);
  for mark in &marks { println!("Mark: {mark}"); }
  println!("Count: {}", marks.len());
  println!("Missing: {:?}", marks.get(3));
}

Expected output

Mark: 70
Mark: 80
Mark: 90
Count: 3
Missing: None

Follow the execution

Push changes the vector length from two to three. The borrowed loop prints each value and leaves marks available for the length check. Index three is outside the collection, so get reports None.

Try the complete program in the Rust compiler. For tests, Cargo commands and local files, use the specified local environment.

Try a small variation

Your task: Why use &marks in the loop when later code still needs the vector?

Rust 2024 · complete program

fn main() {
  let mut marks = vec![70, 80];
  marks.push(90);
  for mark in &marks { println!("Mark: {mark}"); }
  println!("Count: {}", marks.len());
  println!("Missing: {:?}", marks.get(3));
}

Worked answer

It borrows the vector for iteration. Iterating by value over marks would consume this non-Copy vector and prevent using the same binding afterward.

Mistakes and limits to recognize

Capacity is allocated room, while length is the number of initialized elements. Do not read capacity as if it were extra valid marks. Direct indexing can panic; get is useful when absence is an expected input condition.

Check your understanding

Why use &marks in the loop when later code still needs the vector?
Choose one answer. You can try again.

Answer and explanation

It borrows the vector for iteration.

It borrows the vector for iteration. Iterating by value over marks would consume this non-Copy vector and prevent using the same binding afterward.

Take the idea into your next program

It borrows the vector for iteration. Iterating by value over marks would consume this non-Copy vector and prevent using the same binding afterward. Capacity is allocated room, while length is the number of initialized elements.

Further reading: the official Rust Book on vectors and changing collections.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Maps, sets and keyed records →