std::vector::reserve(3)
π std::vector::reserve(3) π
okay so this one's from the C++ Standard Library manual page set, and bestie, it's a good one β reserve() is that girl who plans ahead so the rest of your code doesn't have to panic later. let's get into it π
β¨ Synopsis β¨
void reserve( size_type new_cap ); (constexpr since C++20)
so what this does is bump up the capacity of the vector β and to be clear, capacity is the total number of elements the vector can hold without needing to reallocate β to some value that's greater or equal to new_cap. if new_cap is bigger than the current capacity(), fresh storage gets allocated. otherwise? the function literally does nothing. icon behavior, honestly π
reserve() does not change the size of the vector. size and capacity are two different things, iykyk.
here's the part you need to tattoo on the inside of your brain: if new_cap is greater than capacity(), then all iterators β including the end() iterator β and all references to the elements are invalidated. if it's not greater, then nothing gets invalidated. no cap, this matters π
after you call reserve(), your insertions won't trigger a reallocation unless the insertion would push the vector's size past the value of capacity(). so you did one big planning moment and now you're chilling π¦
πΈ Parameters πΈ
new_capβ the new capacity of the vector, measured in number of elements
π Type requirements π
Tmust meet the requirements ofMoveInsertableinto*this. (since C++11)
β Return value β
none. nothing. void. she gives you nothing back and expects you to be grateful π
π₯ Exceptions π₯
std::length_errorifnew_cap > max_size().- Any exception thrown by
Allocator::allocate()(typicallystd::bad_alloc).
if an exception gets thrown, this function has no effect β that's the strong exception guarantee, and yes she's proud of it π«Ά
and here's a lil caveat: if T's move constructor is not noexcept and T is not CopyInsertable into *this, the vector will use the throwing move constructor. if it throws, the guarantee is waived and the effects are unspecified. so likeβ¦ be aware π (since C++11)
π§ Complexity π§
at most linear in the size() of the container.
π Notes π
okay this is the section where the manpage gets real with you. using reserve() correctly can prevent unnecessary reallocations β slay. but using it inappropriately (say, calling it before every single push_back() call π¬) can actually increase the number of reallocations, because it makes the capacity grow linearly instead of exponentially. which means more computational complexity and decreased performance. it's giving self-sabotage, honestly.
for example: a function that receives an arbitrary vector by reference and appends elements to it should usually not call reserve() on that vector, because it doesn't know the vector's usage characteristics. mind your business, function π
when you're inserting a range, the range version of insert() is generally preferable, because it preserves the correct capacity growth behavior β unlike reserve() followed by a series of push_back()s. the more you know β¨
and one big one: reserve() cannot be used to reduce the capacity of the container. that's not her job. if that's what you want, shrink_to_fit() is provided. go talk to her π
π¦ Example π¦
// Run this code
#include <cstddef>
#include <iostream>
#include <new>
#include <vector>
// minimal C++11 allocator with debug output
template<class Tp>
struct NAlloc
{
typedef Tp value_type;
NAlloc() = default;
template<class T>
NAlloc(const NAlloc<T>&) {}
Tp* allocate(std::size_t n)
{
n *= sizeof(Tp);
Tp* p = static_cast<Tp*>(::operator new(n));
std::cout << "allocating " << n << " bytes @ " << p << '\n';
return p;
}
void deallocate(Tp* p, std::size_t n)
{
std::cout << "deallocating " << n * sizeof *p << " bytes @ " <<
p << "\n\n";
::operator delete(p);
}
};
template<class T, class U>
bool operator==(const NAlloc<T>&, const NAlloc<U>&) { return true; }
template<class T, class U>
bool operator!=(const NAlloc<T>&, const NAlloc<U>&) { return false; }
int main()
{
constexpr int max_elements = 32;
std::cout << "using reserve: \n";
{
std::vector<int, NAlloc<int>> v1;
v1.reserve(max_elements); // reserves at least max_elements *
sizeof(int) bytes
for (int n = 0; n < max_elements; ++n)
v1.push_back(n);
}
std::cout << "not using reserve: \n";
{
std::vector<int, NAlloc<int>> v1;
for (int n = 0; n < max_elements; ++n)
{
if (v1.size() == v1.capacity())
std::cout << "size() == capacity() == " << v1.size() <<
'\n';
v1.push_back(n);
}
}
}
π Possible output π
using reserve:
allocating 128 bytes @ 0xa6f840
deallocating 128 bytes @ 0xa6f840
not using reserve:
size() == capacity() == 0
allocating 4 bytes @ 0xa6f840
size() == capacity() == 1
allocating 8 bytes @ 0xa6f860
deallocating 4 bytes @ 0xa6f840
size() == capacity() == 2
allocating 16 bytes @ 0xa6f840
deallocating 8 bytes @ 0xa6f860
size() == capacity() == 4
allocating 32 bytes @ 0xa6f880
deallocating 16 bytes @ 0xa6f840
size() == capacity() == 8
allocating 64 bytes @ 0xa6f8b0
deallocating 32 bytes @ 0xa6f880
size() == capacity() == 16
allocating 128 bytes @ 0xa6f900
deallocating 64 bytes @ 0xa6f8b0
deallocating 128 bytes @ 0xa6f900
likeβ¦ look at all those reallocations in the second half. that could be you. don't let it be you πβ¨
π Defect reports π
the following behavior-changing defect reports were applied retroactively to previously published C++ standards. retroactive glow-ups, we love to see it π
LWG 329, applied to C++98 β behavior as published: reallocation might be triggered if an insertion makes the size of the vector greater than the size specified in the most recent call toreserve(). correct behavior: only triggers if the size of the vector becomes greater thancapacity().LWG 2033, applied to C++11 β behavior as published:Twas not required to beMoveInsertable. correct behavior: requiredMoveInsertable.
π«Ά See also π«Ά
capacityβ returns the number of elements that can be held in currently allocated storage (public member function)max_sizeβ returns the maximum possible number of elements (public member function)resizeβ changes the number of elements stored (public member function)shrink_to_fit(DR*) β reduces memory usage by freeing unused memory (public member function)
k that's the whole page bestie, go forth and reserve responsibly πβ¨
sign-off vibes: this lil masterpiece lives over at http://cppreference.com, dated 2024.06.10, and it's the std::vector::reserve(3) page β so if you ever need to cite your sources, you know exactly where she came from ππ
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms