Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ standard vector resize() function

resize() adds/removes elements based on the size given to it. reserve() reserves memory space and it will not reallocate memory. The question I have is whether resize also works the same as in the capacity of the vector will only not increase?

To add, would a combination of:

 std::vector<X> vector;
 vector.reserve(5);
 vector.resize(5); 

make any sense? Is it redundant? The goal here is to be able to overwrite values in the vector without having the vector allocate any extra space.

like image 646
Hadi Avatar asked May 12 '16 19:05

Hadi


People also ask

What does vector member size () do?

size() – Returns the number of elements in the vector. max_size() – Returns the maximum number of elements that the vector can hold. capacity() – Returns the size of the storage space currently allocated to the vector expressed as number of elements.

How do you set a vector size?

We can set the size of a Vector using setSize() method of Vector class. If new size is greater than the current size then all the elements after current size index have null values. If new size is less than current size then the elements after current size index have been deleted from the Vector.

How do you expand a vector in C++?

In C++ the length of a vector or any C++ container, is called the size. The vector can be expanded with the following member functions: resize(), insert(), emplace() and push_back(). Other related member functions are: size(), capacity(), and reserve().


5 Answers

From this site:

  • resize(): This lets you change the size of the vector to any size you want.
    • It will fill the underlying buffer with elements.
  • reserve(): This changes the capacity of the vector. Note that this doesn’t change the vector’s size, it just changes the size of the underlying buffer, to give more room for expansion of the buffer before the buffer has to be resized. Unlike calling resize(), this doesn’t change the behavior of the program, just the performance (Subsequent use of the reserved space will not incur a performance penalty for incremental reservations).
    • It will not limit the size of the buffer. If the buffer runs out of space it will automatically reallocate as needed.

enter image description here

The question I have is whether resize also works the same as in the capacity of the vector will only not increase? To add, would a combination of :

 std::vector<X> vector;
 vector.reserve(5);
 vector.resize(5);

make any sense? Is it redundant?

vector.reserve(5); Would be redundant in this case.

The goal here is to be able to overwrite values in the vector without having the vector allocate any extra space.

For this goal it depends on how you want to overwrite the values.

  • If you are planning to write directly by index, then you must use resize().
  • If you are using push_back(), then reserve() would be better so that you can avoid creating X twice.

Keep in mind that the algorithm used for the automatic reservation is implementation defined. See here for more regarding the performance aspect.

like image 65
wally Avatar answered Oct 03 '22 04:10

wally


I don't know where you got your info about reserve, but it will reallocate if the number you pass to it is greater than the vector's current capacity, as reported by the capacity function.

As for resize, it is required to set the number of elements, and if there isn't enough space in the capacity, it will also require a reallocation.

As for your code snippet:

std::vector<X> vector;
vector.reserve(5);
vector.resize(5);

This might make sense if you want to allocate the minimum amount possible in order to store 5 elements. The reason I say that is because resize might allocate more in anticipation for more additions later on (to be clear, this can only happen if the requested size is greater than the capacity. resize will never cause a reallocation if the requested size <= capacity). reserve on the other hand, usually just allocates exactly enough. It is allowed to allocate more, but I have never seen an implementation which does that.

like image 44
Benjamin Lindley Avatar answered Oct 03 '22 03:10

Benjamin Lindley


The main difference between them is that resize lets you change the size (either increase or decrease) while reserve only reserves memory from the system. Resize initialises allocated memory with either a call to default constructor or copy constructor based on form of the resize used.

Both may cause memory reallocation.

like image 41
4pie0 Avatar answered Oct 03 '22 03:10

4pie0


To expand on @BenjaminLindley's answer, in GCC there is definitely a difference.

#include <iostream>
#include <vector>

int main()
{
  std::vector<int> a, b;

  for (std::size_t i=0; i<20; ++i)
  {
    a.reserve(i); a.resize(i); // a: reserve-then-resize
    b.resize(i);               // b: resize directly
    std::cout << a.capacity() << "\t" << b.capacity() << "\n";
  }
}

The output (live demo):

0   0
1   1
2   2
3   4
4   4
5   8
6   8
7   8
8   8
9   16
10  16
11  16
12  16
13  16
14  16
15  16
16  16
17  32
18  32
19  32

So, at least for gcc, reserve-then-resize results in exactly the capacity you asked for, while the direct resize “plans ahead” for expected future allocations.

like image 36
mindriot Avatar answered Oct 03 '22 05:10

mindriot


In some implementations, resize will almost certainly call reserve first. Having recently implemented a variant of std::vector, below is a stripped down and annotated version of std::vector::reserve... (The comments are for the OP's understanding) ...In reality most STL implementations will be slightly more complex than this (for debugging purposes); but its largely the same concept.

template<typename T>
void Vector<T>::reserve(SizeType sz){
        //if only the new size is greater than current capacity
        if(sz > m_capacity){

            //allocate the new size
            T* data = static_cast<T*>(SFAllocator<T>::allocate(sz));

            //move all previous data
            for(SizeType i=0; i < m_size; i++){
                new(data+i) T(std::move(m_data[i]));  //! TODO: move if only noexcept;

                //call the destructor on the moved item
                call_destructor(m_data[i]);
            }

            //deallocate formerly used memory
            SFAllocator<T>::deallocate(m_data);

            //reassign the capacity to the new capacity
            m_capacity = sz;

            m_data = data; //reassign the data pointer
            //size remains the same
        }

And below is a stripped down and annotated version of std::vector::resize. As you can see below, resize has a call to reserve first.

template<typename T>
void Vector<T>::resize(SizeType sz){
    // resize it to fit at least fit to "sz"
    reserve(sz);

    //if higher size is requested
    if(sz > m_size)
        //default construct the remainder of the new uninitialized memory
        for(SizeType i= m_size; i < sz; i++)
            new(m_data+i) T{}

    //if the container size is to get smaller
    else  
        for(SizeType i=sz; i<m_size; i++)
            call_destructor(m_data[i]);  //delete the elements at indexes above "sz"

    m_size = sz;  //change container size.
}
like image 24
WhiZTiM Avatar answered Oct 03 '22 03:10

WhiZTiM