Vec<T> in Depth
Indexing and get()
Vec<T> (and [T]) supports two styles of element and range access: direct indexing (v[index]), which panics on out-of-bounds indices, and checked indexing (v.get(index) / v.get_mut(index)), which returns Option<&T> or Option<&mut T> without panicking.
Comparing v[i] vs. v.get(i)
| Expression | Return Type (Single Index usize) |
Return Type (Range a..b) |
Out-of-Bounds Behavior |
|---|---|---|---|
&v[index] |
&T |
&[T] |
Panics at runtime |
&mut v[index] |
&mut T |
&mut [T] |
Panics at runtime |
v.get(index) |
Option<&T> |
Option<&[T]> |
Returns None |
v.get_mut(index) |
Option<&mut T> |
Option<&mut [T]> |
Returns None |
Single-Element and Range Indexing
Both [index] and .get(index) accept any type implementing std::slice::SliceIndex<[T]>, including a single usize or any range type (a..b, a..=b, ..b, a.., ..):
fn main() {
let mut readings = vec![100, 200, 300, 400];
// 1. Direct indexing (when index is known to be in bounds):
readings[1] = 250;
println!("Element 1: {}", readings[1]);
println!("Slice 1..3: {:?}", &readings[1..3]);
// 2. Checked indexing with `.get()` and `.get_mut()`:
println!("get(2): {:?}", readings.get(2));
println!("get(99): {:?}", readings.get(99));
println!("get(2..10): {:?}", readings.get(2..10));
if let Some(slot) = readings.get_mut(3) {
*slot += 50;
}
println!("After get_mut(3): {readings:?}");
}
Element 1: 250
Slice 1..3: [250, 300]
get(2): Some(300)
get(99): None
get(2..10): None
After get_mut(3): [100, 250, 300, 450]
Disjoint Multi-Element Mutable Access with get_disjoint_mut
When you need mutable references to two or more distinct indices simultaneously (&mut v[i] and &mut v[j]), v.get_disjoint_mut([i, j]) (stabilized in Rust 1.86) checks that all indices are in bounds and pairwise distinct, returning Result<[&mut T; N], GetDisjointMutError>:
fn main() {
let mut accounts = vec![1_000_i64, 500, 2_000];
// Borrow indices 0 and 2 mutably at the same time:
if let Ok([from, to]) = accounts.get_disjoint_mut([0, 2]) {
*from -= 300;
*to += 300;
}
println!("Accounts after transfer: {accounts:?}");
println!(
"Overlapping indices [1, 1]: {:?}",
accounts.get_disjoint_mut([1, 1])
);
}
Accounts after transfer: [700, 500, 2300]
Overlapping indices [1, 1]: Err(OverlappingIndices)
When to Use v[i] vs. v.get(i)
- Use
v.get(i)whenevericomes from external input, user arguments, or arithmetic that might exceedv.len(), or whenNonenaturally drives control flow (if let Some(x) = v.get(i)). - Use
v[i]when an out-of-bounds index represents an internal logic bug in your algorithm and panicking immediately is the intended invariant check.