18.2 The Vec<T>
Vector Type
A Vec<T>
—often called a “vector”—is a dynamic, growable list stored contiguously on the heap. It provides fast indexing, can change size at runtime, and manages its memory automatically. This is conceptually similar to std::vector
in C++ or a manually sized, dynamically allocated array in C, but with Rust’s safety guarantees and automated cleanup.
18.2.1 Creating a Vector
There are several ways to create a new vector:
-
Empty Vector:
let v: Vec<i32> = Vec::new(); // If the type is omitted, Rust attempts type inference.
-
Using the
vec!
Macro:let v1: Vec<i32> = vec![]; // Empty let v2 = vec![1, 2, 3]; // Infers Vec<i32> let v3 = vec![0; 5]; // 5 zeros of type i32
-
From Iterators or Other Data:
let v: Vec<_> = (1..=5).collect(); // [1, 2, 3, 4, 5] let slice: &[i32] = &[10, 20, 30]; let v2 = slice.to_vec(); let array = [4, 5, 6]; let v3 = Vec::from(array);
-
Vec::with_capacity
for Pre-allocation:let mut v = Vec::with_capacity(10); for i in 0..10 { v.push(i); }
This avoids multiple reallocations if you know roughly how many items you will store.
18.2.2 Properties and Memory Management
Under the hood, a Vec<T>
maintains:
- A pointer to a heap-allocated buffer,
- A
len
(the current number of elements), - A
capacity
(the total number of elements that can fit before a reallocation is needed).
When you remove elements, the length decreases but the capacity remains. You can call shrink_to_fit()
if you want to reduce capacity:
let mut v = vec![1, 2, 3, 4, 5];
v.pop();
v.shrink_to_fit(); // Release spare capacity
Rust’s borrowing rules prevent dangling references and out-of-bounds access. If you try to use v[index]
with an invalid index, the program panics at runtime. Meanwhile, v.get(index)
returns None
if the index is out of range.
18.2.3 Basic Methods
push(elem)
: Appends an element (reallocation may occur).pop()
: Removes the last element and returns it, orNone
if empty.get(index)
: ReturnsOption<&T>
safely.- Indexing (
[]
): Returns&T
, panics if the index is invalid. len()
: Returns the current number of elements.insert(index, elem)
: Inserts an element at a specific position, shifting subsequent elements.remove(index)
: Removes and returns the element at the given position, shifting elements down.
18.2.4 Accessing Elements
let v = vec![10, 20, 30];
// Panics on invalid index
println!("First element: {}", v[0]);
// Safe access using `get`
if let Some(value) = v.get(1) {
println!("Second element: {}", value);
}
// `pop` removes from the end
let mut v2 = vec![1, 2, 3];
if let Some(last) = v2.pop() {
println!("Popped: {}", last);
}
18.2.5 Iteration Patterns
// Immutable iteration
let v = vec![1, 2, 3];
for val in &v {
println!("{}", val);
}
// Mutable iteration
let mut v2 = vec![10, 20, 30];
for val in &mut v2 {
*val += 5;
}
// Consuming iteration (v3 is moved)
let v3 = vec![100, 200, 300];
for val in v3 {
println!("{}", val);
}
18.2.6 Handling Mixed Data
All elements in a Vec<T>
must be of the same type. If you need different types, consider:
- An
enum
that encompasses all possible variants. - Trait objects (e.g.,
Vec<Box<dyn Trait>>
) for runtime polymorphism.
For example, using an enum
:
enum Value { Integer(i32), Float(f64), Text(String), } fn main() { let mut mixed = Vec::new(); mixed.push(Value::Integer(42)); mixed.push(Value::Float(3.14)); mixed.push(Value::Text(String::from("Hello"))); for val in &mixed { match val { Value::Integer(i) => println!("Integer: {}", i), Value::Float(f) => println!("Float: {}", f), Value::Text(s) => println!("Text: {}", s), } } }
Using trait objects adds overhead due to dynamic dispatch and extra heap allocations. Choose the approach that best meets your performance and design needs.
18.2.7 Summary: Vec<T>
vs. C
In C, you might manually manage an array with malloc
/realloc
/free
, tracking capacity yourself. Rust’s Vec<T>
automates these tasks, prevents out-of-bounds access, and reclaims memory when the vector goes out of scope. This significantly reduces memory-management errors while still allowing fine-grained performance tuning (e.g., pre-allocation via with_capacity
).