Reputation: 1685
I'm trying to figure out how the memory management for std::vector works when you remove elements. It is my understanding that once memory was allocated for the vector, no pop_back\erase action would reduce the capacity of the vector, and the only way to do so is using shrink_to_fit which was introduced in C++ 11. Please correct me if I'm wrong.
Upvotes: 0
Views: 322
Reputation: 218710
You are correct, mostly.
There are only a few ways to reduce a std::vector
's capacity…
Move Assignment
#include <iostream>
#include <vector>
int
main()
{
std::vector<int> v1(10);
std::vector<int> v2(20);
std::cout << "v2.capacity() = " << v2.capacity() << '\n';
std::cout << "Move assign v2 with less capacity\n";
v2 = std::move(v1);
std::cout << "v2.capacity() = " << v2.capacity() << '\n';
}
which should output:
v2.capacity() = 20
Move assign v2 with less capacity
v2.capacity() = 10
If the allocator involved is set a certain way, diminished capacity is not assured. But in the common case as shown above, capacity will shrink. If you really want to know about the nitty gritty details of how capacity might not shrink during move assignment, ask another question, and I can dig into that in detail.
shrink_to_fit
#include <iostream>
#include <vector>
int
main()
{
std::vector<int> v(20);
std::cout << "v.capacity() = " << v.capacity() << '\n';
std::cout << "erasing...\n";
v.erase(v.begin() + v.size()/2, v.end());
std::cout << "v.capacity() = " << v.capacity() << '\n';
std::cout << "shrink_to_fit...\n";
v.shrink_to_fit();
std::cout << "v.capacity() = " << v.capacity() << '\n';
}
which will probably output:
v.capacity() = 20
erasing...
v.capacity() = 20
shrink_to_fit...
v.capacity() = 10
But it is allowed to output:
v.capacity() = 20
erasing...
v.capacity() = 20
shrink_to_fit...
v.capacity() = 20
swap
#include <iostream>
#include <vector>
int
main()
{
std::vector<int> v(20);
std::vector<int> v2(10);
std::cout << "v.capacity() = " << v.capacity() << '\n';
std::cout << "swap...\n";
swap(v, v2);
std::cout << "v.capacity() = " << v.capacity() << '\n';
}
which should output:
v.capacity() = 20
swap...
v.capacity() = 10
I know of no other ways to shrink the capacity of a vector
(besides obviously equivalent constructs such as v.swap(v2)
).
A good rule of thumb is that the capacity of a vector never shrinks unless:
swap
).shrink_to_fit
is called.Oh, and I nearly forgot a third possibility: any time you move from a vector
, the moved-from vector
might have a diminished capacity (or it might not). It is unspecified, so you can't count on it. In general moved-from values should be variables where you don't care what their current state is. You will subsequently destruct them or assign them a new known state (assignment doesn't have to be via the assignment operator; could be clear()
followed by push_back()
for example).
Upvotes: 2