C++ vector reserve vs resize: When to Use Which (Complete Guide)

C++ vector reserve vs resize: When to Use Which (Complete Guide)

이 글의 핵심

A practical guide to C++ vector reserve vs resize: capacity vs size, benchmarks, and patterns.

Contiguous dynamic arrays (like std::vector) are the usual way to implement the “array” side of arrays and lists—this article focuses on capacity vs length inside that model.

Introduction: “Should I use reserve or resize?"

"Don’t both make the vector bigger?”

In C++, vector::reserve and resize do completely different things. reserve only increases capacity; resize changes size and initializes elements.

std::vector<int> vec;

// reserve: capacity only
vec.reserve(100);
std::cout << vec.size() << '\n';      // 0
std::cout << vec.capacity() << '\n';  // 100

// resize: size + initialization
vec.resize(100);
std::cout << vec.size() << '\n';      // 100
std::cout << vec.capacity() << '\n';  // 100

This article covers:

  • reserve vs resize
  • Performance comparison
  • Usage scenarios
  • Practical tips

Table of contents

  1. reserve vs resize
  2. Performance
  3. Usage scenarios
  4. Examples
  5. Summary

1. reserve vs resize

reserve: capacity only

std::vector<int> vec;

vec.reserve(5);  // capacity at least 5

std::cout << vec.size() << '\n';      // 0 (unchanged)
std::cout << vec.capacity() << '\n';  // 5

// vec[0] = 42;  // undefined behavior (size is 0)

vec.push_back(10);  // OK
std::cout << vec.size() << '\n';  // 1

resize: size change + initialization

std::vector<int> vec;

vec.resize(5);  // size 5, value-initialized to 0

std::cout << vec.size() << '\n';      // 5
std::cout << vec.capacity() << '\n';  // at least 5

vec[0] = 42;  // OK
std::cout << vec[0] << '\n';  // 42
std::cout << vec[1] << '\n';  // 0 (initialized)

Comparison table

Aspectreserve(n)resize(n)
sizeUnchangedbecomes n
capacityat least nat least n
InitializationNonedefault value
Index accessOnly within sizeYes
push_backYesYes

2. Performance

Benchmark: push_back

#include <benchmark/benchmark.h>

// No reserve
static void BM_PushBack_NoReserve(benchmark::State& state) {
    for (auto _ : state) {
        std::vector<int> vec;
        for (int i = 0; i < 1000000; ++i) {
            vec.push_back(i);
        }
    }
}
BENCHMARK(BM_PushBack_NoReserve);

// With reserve
static void BM_PushBack_Reserve(benchmark::State& state) {
    for (auto _ : state) {
        std::vector<int> vec;
        vec.reserve(1000000);
        for (int i = 0; i < 1000000; ++i) {
            vec.push_back(i);
        }
    }
}
BENCHMARK(BM_PushBack_Reserve);

// resize
static void BM_Resize(benchmark::State& state) {
    for (auto _ : state) {
        std::vector<int> vec;
        vec.resize(1000000);
        for (int i = 0; i < 1000000; ++i) {
            vec[i] = i;
        }
    }
}
BENCHMARK(BM_Resize);

Results (GCC 13, -O3):

BM_PushBack_NoReserve    50 ms  (many reallocations)
BM_PushBack_Reserve      10 ms  (no reallocations)
BM_Resize                 8 ms  (fastest)

3. Usage scenarios

reserve: before push_back

// reserve: grow with push_back
std::vector<int> vec;
vec.reserve(1000);

for (int i = 0; i < 1000; ++i) {
    vec.push_back(i);
}

resize: index access

// resize: direct indexing
std::vector<int> vec;
vec.resize(1000);

for (int i = 0; i < 1000; ++i) {
    vec[i] = i;
}

resize: fill with a value

// resize: initialize to a specific value
std::vector<int> vec;
vec.resize(1000, 42);

std::cout << vec[0] << '\n';    // 42
std::cout << vec[999] << '\n';  // 42

4. Examples

Example 1: reading a file

// reserve: unknown line count
std::vector<std::string> lines;
lines.reserve(1000);

std::ifstream file("data.txt");
std::string line;
while (std::getline(file, line)) {
    lines.push_back(line);
}

Example 2: converting from an array

// resize: known size
int arr[100] = {/* ... */};

std::vector<int> vec;
vec.resize(100);

for (int i = 0; i < 100; ++i) {
    vec[i] = arr[i];
}

Example 3: 2D matrix

// resize: 2D vector
std::vector<std::vector<int>> matrix;
matrix.resize(10);

for (auto& row : matrix) {
    row.resize(20, 0);
}

matrix[5][10] = 42;

Summary

Choosing reserve vs resize

SituationUse
Growing with push_backreserve
Direct index accessresize
Unknown final sizereserve
Known size + initializationresize
Avoid reallocations onlyresize
Need element initializationresize

Rules of thumb

  1. push_back → reserve
  2. Index access → resize
  3. Need initialization → resize
  4. Reallocations only → reserve

Checklist

  • If you use push_back, do you reserve?
  • If you index, do you resize first?
  • Do you need default initialization?
  • Is performance critical?

  • C++ vector basics guide
  • C++ vector vs list vs deque
  • C++ performance optimization
  • C++ STL containers guide

Keywords (SEO)

vector reserve, vector resize, reserve vs resize, vector performance, avoid reallocation

Practical tips

Debugging

  • Indexing after reserve only (size still 0) is undefined behavior.
  • push_back after resize still grows size.
  • capacity rarely shrinks without shrink_to_fit.

Performance

  • reserve before push_back loops to avoid reallocations.
  • Index-heavy code can be faster with resize + assignment.
  • If you do not need initialization, prefer reserve + push_back.

Code review

  • Check reserve in hot push_back loops.
  • Find index writes without prior resize.
  • Replace unnecessary resize with reserve when only capacity matters.

Closing

reserve avoids reallocations; resize changes length and initializes.

Takeaways:

  1. push_back → reserve
  2. Index access → resize
  3. Hot paths → reserve

If you use push_back, reserve is the usual way to win performance.

Next: dig deeper in the C++ STL container guides.