C++ vector vs array: which should you use?
The short answer first, then the details that actually matter in interviews and real code.
The 10-second answer
Default to std::vector. Use a C-style array only when a fixed size is part of the problem (and use std::array rather than the raw kind). Everything below explains why, because "just use vector" won't survive a follow-up question.
Three containers, one idea
| C-style array | std::array | std::vector | |
|---|---|---|---|
| Size | Fixed at compile time | Fixed at compile time | Grows and shrinks at runtime |
| Lives where? | Where you declare it (stack if local) | Where you declare it | Data on the heap; object itself can live anywhere |
| Knows its length? | No — you track it separately | Yes — .size() | Yes — .size() |
| Copyable? | No (decays to a pointer) | Yes | Yes |
| Pass to a function | Awkward (becomes a pointer, size is lost) | Clean | Clean |
| Bounds checking | None | .at() checks | .at() checks, [] doesn't |
What each looks like
#include <array>
#include <vector>
int main() {
int raw[5] = {1, 2, 3, 4, 5}; // C-style: size is part of the type
std::array<int, 5> fixed = {1, 2, 3, 4, 5}; // fixed size, but a real type
std::vector<int> grow = {1, 2, 3}; // resizable
grow.push_back(4); // now holds 1 2 3 4
return 0;
}
Note: our in-browser playground currently covers the beginner core (iostream, cmath, cstdio…), so run snippets like these on your desktop compiler — or in the playground once full-container support lands.
Why vector wins by default
- Size at runtime. Most real data isn't a known length at compile time: a file's lines, a user's input, network messages. A vector resizes; an array can't.
- It remembers its length. Passing a raw array into a function silently turns it into a pointer — the classic source of bugs and buffer overflows. A vector carries
.size()everywhere it goes. - It's fast anyway. Vector storage is one contiguous block of memory, exactly like an array. Iterating over a vector is typically the same speed as iterating over an array once you're past the initial capacity growth. If you know the final size, call
reserve(n)first and there's almost nothing left to pay. - It plays well with everything — range-based for loops, algorithms like
std::sort, and the rest of the standard library.
When an array (the fixed kind) is genuinely better
- The size is fixed by the problem: days of the week, a chess board (8×8), RGB (3 components).
- You're in a hot loop on an embedded target and want zero heap use —
std::arraynever allocates. - You need the object on the stack and know it's small.
Interview follow-ups worth knowing
- "How does vector grow?" When it hits capacity, it allocates a bigger block (commonly ~1.5× or 2×) and moves elements over — that's why repeated
push_backis still amortized O(1). - "What's vector<bool>?" A trick question: it's a bit-packed specialization that doesn't behave like a normal vector of values.
- "Difference between
size()andcapacity()?"size()= elements in use;capacity()= slots allocated before the next regrow. - "Can vector invalidate pointers?" Yes — any growth or
insert/erasemay move the storage. Don't keep raw pointers/references into a vector across modifications.
Rule of thumb
Write std::vector until you have a measured reason not to. Fixed-size-by-nature? Reach for std::array. Raw C arrays are for interfacing with C code and memory-constrained embedded work — and even then, wrapped.