What is the difference between an array and a Vec?
Short answer: an array [T; N] carries its length in the type and stores its elements inline,
usually on the stack; a Vec<T> keeps its elements on the heap and grows at run time. Both index
the same way and hand out slices, so reading code takes &[T].
Each block below is a complete src/main.rs; the blocks that print run with cargo run, the
failing one with cargo build. Rust 1.99.0, edition 2024.
The length is in the type
Section titled “The length is in the type”[i32; 3] and [i32; 4] are different types, and the length can’t wait until run time — not even
for a variable holding a 3:
fn main() { let n = 3; let nums = [0; n]; println!("{nums:?}");}error[E0435]: attempt to use a non-constant value in a constant --> src/main.rs:3:20 |3 | let nums = [0; n]; | ^ non-constant value |help: consider using `const` instead of `let` |2 - let n = 3;2 + const n: /* Type */ = 3; |
For more information about this error, try `rustc --explain E0435`.A Vec’s length is a value it carries, so it can come from anywhere.
Where the elements live
Section titled “Where the elements live”fn main() { println!("[i32; 3] is {} bytes", std::mem::size_of::<[i32; 3]>()); println!("Vec<i32> is {} bytes", std::mem::size_of::<Vec<i32>>());}[i32; 3] is 12 bytesVec<i32> is 24 bytesThree i32s in an array are twelve bytes sitting where the array sits — on the stack for a
local binding. A Vec<i32> is a twenty-four-byte header (pointer, length, capacity) aimed at a
heap allocation. Creating the Vec allocates; growing past the capacity allocates a bigger buffer
and copies the elements across.
What they share
Section titled “What they share”Both index with [i] and answer len(), iter() and first(): an array coerces to a
slice, a Vec derefs to one, and the slice methods resolve on both. A function that only reads
should take &[T]:
fn total(values: &[i32]) -> i32 { values.iter().sum()}
fn main() { let array = [1, 2, 3]; let vec = vec![10, 20, 30]; println!("{}", total(&array)); println!("{}", total(&vec));}660Moving between them
Section titled “Moving between them”Vec::from([1, 2, 3]) and [1, 2, 3].to_vec() copy the elements into a fresh Vec; going back
needs the length in the type: try_into returns an Err when the count doesn’t match. An array
of Copy elements is Copy, so passing one to a function copies it; a Vec moves.
Which one to reach for
Section titled “Which one to reach for”A count the compiler can see — the days of the week, a grid’s dimensions — is an array; a count
that arrives from outside is a Vec. In doubt, start with Vec.
Related
Section titled “Related”- What is the difference between a Vec and a slice? — the owner behind a slice
- Why does indexing an array out of bounds panic?
- How to accept both a Vec and a slice in one function —
the
&[T]signature
Next in this chapter: how to tell the compiler the type of an empty Vec.