C++ Array vs vector: Performance, Safety, and When to Use Each
이 글의 핵심
Practical guide: C arrays vs std::array vs std::vector—performance, safety, and selection criteria.
For arrays vs linked lists in algorithm interviews (cache locality, insertion cost), see arrays and lists—it complements choosing among C++ array flavors here.
Introduction: “Array or vector?"
"I heard arrays are faster, but everyone says use vector”
C++ offers C-style arrays, std::array, and std::vector. They differ in storage, resize capability, and safety.
int arr1[5] = {1, 2, 3, 4, 5};
std::array<int, 5> arr2 = {1, 2, 3, 4, 5};
std::vector<int> vec = {1, 2, 3, 4, 5};
This article covers:
- Differences among the three
- Performance benchmarks
- Memory safety
- Selection guide
Table of contents
1. Three array kinds
Comparison table
| Aspect | C array | std::array | std::vector |
|---|---|---|---|
| Storage | Usually stack | Usually stack | Heap |
| Size | Fixed (compile-time) | Fixed (compile-time) | Dynamic |
| Bounds check | No | at() | at() |
| Size query | sizeof hacks | size() | size() |
| STL algorithms | Partial | Full | Full |
| Function args | Decays to pointer | By value/ref | Typically const ref |
| Safety | Low | High | High |
C-style array pitfalls
int arr[5] = {1, 2, 3, 4, 5};
// arr[10] = 99; // undefined behavior
void foo(int arr[]) { /* sizeof(arr) is pointer size */ }
std::array (C++11)
#include <array>
std::array<int, 5> arr = {1, 2, 3, 4, 5};
arr.at(10); // throws std::out_of_range
std::sort(arr.begin(), arr.end());
std::vector
#include <vector>
std::vector<int> vec = {1, 2, 3, 4, 5};
vec.push_back(6);
vec.resize(10);
vec.at(10); // throws if out of range
2. Benchmarks
Test 1: element access
Result (typical optimized builds): same order of magnitude for indexed access over large iteration counts.
Test 2: create/destroy in a loop
Stack arrays / std::array: cheap construction.
vector: heap allocation/deallocation dominates if you repeatedly create huge vectors in inner loops.
Test 3: iteration
Range-for and indexed loops are typically comparable when optimized.
3. Memory safety
Bounds checking
Use at() when you want exceptions on out-of-range access; operator[] is unchecked (fast, sharp).
Passing arrays to functions
Prefer std::array<T,N> or const std::vector<T>& so length travels with the data.
4. Selection guide
Decision sketch
Fixed size known at compile time?
No -> std::vector
Yes -> Small (< ~100) -> std::array often fine
Large buffer -> vector (avoid huge stack frames)
Recommendations
| Situation | Prefer |
|---|---|
| Default | std::vector |
| Small fixed buffer, hot ctor/dtor | std::array |
| Dynamic size | std::vector |
| Interop with C APIs | raw arrays only at the boundary |
Examples
Fixed small buffer:
std::array<char, 1024> buffer;
readData(buffer.data(), buffer.size());
Dynamic list:
std::vector<int> numbers;
numbers.reserve(100);
for (int i = 0; i < n; ++i) numbers.push_back(i);
3D coordinate:
struct Position {
std::array<float, 3> coords;
};
Summary
Default: std::vector.
Fixed small N: std::array.
Avoid raw C arrays except FFI boundaries.
Next: read the vector deep-dive in the series.
Related reading
- C++ vector guide
- Memory basics
- Stack overflow pitfalls
Keywords
array vs vector, std::array, stack vs heap, C++ performance
Practical tips
- Use
at()in debug-heavy workflows; keep[]where you have proven invariants. reserve()for known growth patterns.- Watch stack size for large
std::arraylocals.
Related posts
- Browse the C++ series
- C++ Adapter Pattern
- C++ ADL
- Aggregate initialization