Course contentsShow
← Rust
Lesson 344 of 1,9104. Lifetimes and Advanced OwnershipFree lesson

Borrowing vs Moving in Iterators

Optimize collection traversal by choosing the correct ownership strategy.

In this lesson, you will learn how to choose between consuming a collection or simply peeking at its elements to optimize performance and memory safety.

When working with iterators in Rust, the way you access your data determines whether you are "using up" the collection or simply looking at it. This choice is defined by three primary traits: IntoIterator, Iterator, and IntoIterator with references.

The Strategy of Moving

When you iterate over a collection using a for loop, you are implicitly calling into_iter(). This moves the elements out of the collection. Once the loop finishes, the original collection is gone because its ownership has been transferred to the iterator.

let strings = vec![String::from("Rust"), String::from("Iterators")];

// This consumes the vector; 'strings' is no longer accessible!
for s in strings {
    println!("{}", s);
}

This is highly efficient if you no longer need the container, as it avoids unnecessary cloning or reference management.

The Strategy of Borrowing

If you want to keep the collection intact, you must iterate by borrowing. You do this by calling .iter() (which yields immutable references &T) or .iter_mut() (which yields mutable references &mut T).

let strings = vec![String::from("Rust"), String::from("Iterators")];

// We use .iter() to borrow elements.
// The vector 'strings' is still perfectly valid here.
for s in strings.iter() {
    println!("{}", s);
}

println!("Vector length is: {}", strings.len());

When to Choose Which?

  • Move (into_iter): Use this when you are transforming data, filtering, or simply finishing a task where the container is no longer needed. It is the most "destructive" but often the most performant approach if you need to own the inner values.
  • Borrow (iter / iter_mut): Use this when you need to inspect or modify elements in place without invalidating the container. This respects the borrow checker's rules while keeping your memory footprint low by avoiding clones.

By understanding the cost of ownership, you prevent accidental moves that lead to "use of moved value" errors while ensuring your code doesn't unnecessarily clone data.

Key Takeaway: Use into_iter() to consume a collection by moving its contents, or use iter() and iter_mut() to borrow elements if you need to keep the collection alive.