C++ vector: reserve vs. resize

黎 浩然/ 7 10 月, 2026/ C/C++/ 0 comments

reserve(n) prepares capacity without changing the element count. resize(n) changes the count to n. After reserve(100), you cannot write the hundredth element through v[99]. Valid indices depend on size(), not capacity().

Contents
  1. Size and capacity are different
  2. Comparing reserve and resize
  3. A runnable C++17 example
  4. Capacity does not permit indexed writes
  5. Why can growth invalidate references?
  6. When should you reserve in advance?
  7. Three quick decisions
  8. References

中文版 / Chinese version

Size and capacity are different

Think of a vector as contiguous stored elements. size() is the current number of elements. capacity() is how many elements it can accommodate without reallocating storage. Unused capacity is not a set of vector elements you may access by index.

For an ordinary std::vector<T>, valid indices satisfy 0 ≤ i < size() ≤ capacity().

C++ vector: reserve vs. resize: original technical diagram
Original illustration. Gray cells are unused capacity. The diagram assumes capacity 6 initially and after reserve(6); the API guarantees at least 6, not exactly 6.

Comparing reserve and resize

Operation Size Capacity Typical use
reserve(n) Unchanged Grows to at least n if needed Prepare for later appends
resize(n) Becomes n May grow; shrinking size does not shrink capacity Create elements before assigning by index
resize(n, value) Becomes n Same capacity rules Initialize new elements with a specified value

reserve’s argument is not additional capacity. If size is 20 and the intended total is 100, consider reserve(100), rather than interpreting it as “add 100 slots.”

A runnable C++17 example

#include <cassert>
#include <iostream>
#include <stdexcept>
#include <vector>
int main() {
    std::vector<int> v{10, 20};
    v.reserve(6);
    assert(v.size() == 2 && v.capacity() >= 6);
    std::cout << "reserve: size=" << v.size()
              << ", capacity>=6=" << (v.capacity() >= 6) << '\n';
    try { (void)v.at(2); }
    catch (const std::out_of_range&) { std::cout << "at(2): out_of_range\n"; }
    v.resize(4);
    assert((v == std::vector<int>{10, 20, 0, 0}));
    std::cout << "resize(4):";
    for (int x : v) std::cout << ' ' << x;
    std::cout << '\n';
    const auto capacity = v.capacity();
    v.resize(1);
    assert(v.size() == 1 && v.capacity() == capacity);
    std::cout << "resize(1): size=" << v.size()
              << ", capacity unchanged=" << (v.capacity() == capacity) << '\n';
    std::vector<int> empty;
    empty.reserve(0);
    empty.resize(0);
    assert(empty.empty());
}

Compilation and execution:

clang++ -std=c++17 -Wall -Wextra -pedantic vector-reserve-resize.cpp -o demo
./demo

The example was compiled and executed; output:

reserve: size=2, capacity>=6=1
at(2): out_of_range
resize(4): 10 20 0 0
resize(1): size=1, capacity unchanged=1

It checks capacity() >= 6 rather than printing a fixed capacity because standard-library allocation policies can differ. Boolean 1 means the condition holds.

With the default allocator, resize(4) adds two zero-valued elements to this vector<int>. Class types follow their default-construction behavior; not every type is initialized to zero. resize(4, 7) initializes new elements to 7 and leaves the existing 10 and 20 unchanged.

Capacity does not permit indexed writes

std::vector<int> v;
v.reserve(100);
// v[0] = 42;  // Invalid: size is still 0; undefined behavior in C++17.
v.push_back(42);  // Append an element first.

For a fixed-size result populated by index, construct the elements first:

std::vector<int> result(100);
result[0] = 42;  // Index 0 is valid.

at(i) checks the index and throws std::out_of_range when it is invalid. C++17 operator[] does not provide that exception check. A program avoiding a crash is not evidence that an access was valid.

Why can growth invalidate references?

Reallocation can move existing elements into new storage. Pointers, references, and iterators to the old locations then become invalid. The mechanism does not depend on a particular growth multiplier.

std::vector<int> v{10, 20};
int& first = v[0];
v.reserve(v.capacity() + 1);  // Reallocates if within max_size() and allocation succeeds.
// Do not use first again; obtain v[0] anew.

If n does not exceed current capacity, reserve(n) does not reallocate and existing element references remain valid. If resize removes tail elements, references to those removed elements become invalid. “No growth” does not mean “all references remain valid forever.”

The earlier article on C++ value and reference parameters (Chinese) discusses parameters and objects. Here the container also controls object lifetime and storage location.

When should you reserve in advance?

Reserve once when the final scale can be estimated, for example when reading a known number of records or producing a fixed-count result. Adding m elements to a vector with k elements calls for considering k + m, including addition overflow and the container limit.

Do not call reserve(size() + 1) before every push_back. It can interfere with the library’s growth policy and cause repeated reallocations. The standard does not require each expansion to double capacity.

An individual append that reallocates must transfer existing elements. Ordinary consecutive push_back operations have amortized constant complexity. Reserving avoids unnecessary reallocations; it does not make every operation strictly constant-time.

Three quick decisions

  • To reduce later append reallocations, consider reserve.
  • To have n immediately accessible elements, use resize or a size-taking constructor.
  • To reduce capacity, resize is not the operation; shrink_to_fit is a non-binding request and need not release storage.

References

The working draft is updated continuously and may show declarations or interfaces introduced after C++17. The examples here use C++17 interfaces.

English edition added on October 7, 2026, after the Chinese edition. The article date matches the Chinese edition; it is not the actual time this English edition became public.

Support

If this article helped you, you can support this site.

WeChat support QR code; click to enlarge
WeChat
Alipay support QR code; click to enlarge
Alipay
Buy Me a Coffee; support this site
Buy Me a Coffee

Click a QR code to enlarge. More options: support page。

Share this Post

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注

*
*