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.
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.
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.
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().
From this site:
resize()
: This lets you change the size of the vector to any size you want.
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).
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.
resize()
.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.
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.
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.
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.
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.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With