reserve() in C++. Trade-off between Speed and Memory Utilization
Overview
std::string::reserve() pre-allocates capacity for a string. If we know the final size of the result, reserving that capacity up front avoids repeated reallocations and copying during concatenation.
This is mainly a memory-allocation efficiency technique. It can also improve runtime, but this write-up focuses on memory behavior.
Task
- Given (for example):
const std::vector<std::string>& words = {"hello", "42"}; -
Task: Concatenate all elements of words into a single string and return it.
- Expected result:
std::string result = concatWords(words); result == "hello42"; // true - Constraints:
- Memory usage efficiency is the priority
- Runtime performance is not the primary concern
Solution: 2 Options
Option 1: Allocation-naive
std::string concatWords(const std::vector<std::string>& words) {
std::string s;
for (const auto& w : words)
s.append(w);
return s;
}
-
The string grows dynamically
-
May reallocate memory multiple times
Option 2: Memory-efficient
std::string concatWords(const std::vector<std::string>& words) {
size_t total = 0;
for (const auto& w : words)
total += w.size();
std::string s;
s.reserve(total);
for (const auto& w : words)
s.append(w);
return s;
}
- Exactly one allocation
- No buffer growth
- No copying of previously written data
—
In Option1 std::string::append() will reallocate memory when the current buffer capacity is smaller than the required size of the new string.
In Option 2 calling reserve(total) guarantees that the string’s internal buffer has at least total bytes of capacity, so no memory reallocation will occur while appending up to that size.
Conclusion
std::string::reserve()allows to control memory growth and prevent repeated reallocations during concatenation.- When the final size is known, reserving capacity up front produces the same result with fewer allocations and less memory movement, making it the correct approach when memory efficiency matters.