As std::vector is a dynamic array, we could be able to change its size. Yes, we can do that using a member function it provides .resize() which takes a new desired length(or size).

std::vector items{1, 2, 3};
std::cout << items.size() << "\n"; // 3
 
// resizing
 
items.resize(5);
std::cout << items.size() << "\n"; // 5

If we look at the items, we should see

void printElements(const std::vector<int> &items)
{
    for (const auto &item : items)
    {
        std::cout << item << " ";
    }
 
    std::cout << '\n';
}
 
printElements(items); // items resized to 5

Output:

1 2 3 0 0

As we have increase the size of the vector, existing items are still present but two new elements value-initialized to zero are added.

Reallocation

resize() changes the amount of memory being used by vector to accommodate desired number of elements. The process of changing the storage is called reallocation. Reallocation processes for a vector consists following operations:

  1. Acquire new memory to fulfill the capacity of desired number of elements to store and value initialize new members.
  2. Copy old members (possibly move) to new memory location and old memory is returned back to the system.
  3. Update vector length and its capacity (if required, because if vector already has capacity for desired length)

These operations are expensive to perform and so unnecessary reallocation should mostly be avoided.

Warning

Due to reallocation, the elements move to new memory block and if there are any references to those elements, those references get invalidated. Accessing those invalidated references result in undefined results.

Resizing to smaller value may not free up the memory

Suppose a vector has total 5 elements and we have resized it to have total 6 elements(1 more).

std::vector items{1, 2, 3, 4, 5};
items.resize(6);
 
printElements(items); // 1, 2, 3, 4, 5, 0
printSize(items); // 6

Now that it has storage of 6 elements, if we resize it to 3,

items.resize(3);
printElements(items); // 1, 2, 3
printSize(items); // 3

the size of items reduces to 3 and it prints 3 elements. But, vector may still hold storage space for total 6 elements. We can verify that by printing capacity.

#include <iostream>
#include <vector>
 
void printCapacityLength(const std::vector<int> &items)
{
    std::cout << "Capacity: " << items.capacity() << " | Length: " << items.size() << "\n";
}
 
void printElements(const std::vector<int> &items)
{
    for (const auto &item : items)
    {
        std::cout << item << " ";
    }
 
    std::cout << '\n';
}
 
int main(int argc, char const *argv[])
{
    std::vector items{1, 2, 3, 4, 5};
 
    std::cout << "Original\n";
    printCapacityLength(items);
    printElements(items);
 
    std::cout << "Resize=6\n";
    items.resize(6);
    printCapacityLength(items);
    printElements(items);
 
    std::cout << "Resize=3\n";
    items.resize(3);
    printCapacityLength(items);
    printElements(items);
 
    return 0;
}

It prints following on author machine:

Original
Capacity: 5 | Length: 5
1 2 3 4 5
Resize=6
Capacity: 10 | Length: 6
1 2 3 4 5 0
Resize=3
Capacity: 10 | Length: 3
1 2 3

Please not that the initial capacity was 5 as we initialized vector with 5 elements. When we resize it to 6, the size is 6 but the capacity is 10 (we may expect 6 but it is based on the implementation and implementation may give more capacity so that future reallocations would be lesser).

Next, when we resize the vector to 3, the size is decreased but the capacity is still 10. So, the memory is not freed up. This means the reallocation hasn’t happened, which is efficient as doing reallocation just to free 3 elements is expensive.

Shrinking a vector

We can force a vector to free up the memory not in used after the resize is done using shrink_to_fit() member function. For example,

// ... above statements
std::cout << "Shrinking to last resize\n";
items.shrink_to_fit();
printCapacityLength(items);
printElements(items);

When we execute it, we should see following output:

Original
Capacity: 5 | Length: 5
1 2 3 4 5
Resize=6
Capacity: 10 | Length: 6
1 2 3 4 5 0
Resize=3
Capacity: 10 | Length: 3
1 2 3
Shrinking to last resize
Capacity: 3 | Length: 3
1 2 3

Now we see that capacity is also reduced to 3 because shrink_to_fit has reallocated memory for just 3 elements.

References

  1. https://www.learncpp.com/cpp-tutorial/stdvector-resizing-and-capacity/