user181218
user181218

Reputation: 1685

Memory deallocation in std::vector

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

Answers (1)

Howard Hinnant
Howard Hinnant

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:

  1. It transfers resources with another vector (e.g. move assignment or swap).
  2. 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

Related Questions