Skip to content
Select theme

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.

[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:

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.

[i32; 3] is 12 bytes
Vec<i32> is 24 bytes

Three 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.

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]:

6
60

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.

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.

Next in this chapter: how to tell the compiler the type of an empty Vec.