7

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.

Hadi
  • 945
  • 3
  • 10
  • 31
  • As a test, using Visual Studio I noted that the capacity remains the same for bot resize and reserve. However, this could be some optimization on part of VS's compiler. – Hadi May 12 '16 at 19:58
  • 5
    *"reserve() reserves memory space and it will not reallocate memory"* -- Is that supposed to be a question? Because if it's a statement, it's wrong. – Benjamin Lindley May 12 '16 at 19:59
  • 1
    *reserve() reserves memory space and it will not reallocate memory*. Who told you that? `reserve` will allocate more memory if the size requested is greater than the capacity. – NathanOliver May 12 '16 at 20:00
  • 1
    May be you shoud start by reading http://en.cppreference.com/w/cpp/container/vector/resize and http://en.cppreference.com/w/cpp/container/vector/reserve ? – SergeyA May 12 '16 at 20:02
  • Short and very simplified, `reserve` sets the capacity and `resize` sets the size (and possibly the capacity as well). – Some programmer dude May 12 '16 at 20:02
  • yes my question is basically the 'possibly' part. Will resize() cap the capacity to avoid further capacity increases? – Hadi May 12 '16 at 20:03
  • In order to "overwrite values in the vector without having the vector allocate any extra space" you do not need any of these. just use `vector[i] = x` to overwrite a value. – Frank Puffer May 12 '16 at 20:09
  • "reserve() reserves memory space and it will not reallocate memory" appears to be nonsense under all reasonable interpretations. C++ does not have a concept of reserving an address range (like virtual allocation). And `reserve` will necessarily allocate a new buffer if the capacity isn't already already as large as the call specifies. – Cheers and hth. - Alf May 12 '16 at 21:02
  • Obtain a grounded understanding of _abstraction_ and you will understand `std::vector` ... and the rest of C++. "Size" has many meanings, all of them based on context. – Lightness Races in Orbit May 12 '16 at 21:19

5 Answers5

8

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.

Community
  • 1
  • 1
wally
  • 10,717
  • 5
  • 39
  • 72
4

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.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
3

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.

4pie0
  • 29,204
  • 9
  • 82
  • 118
3

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.

mindriot
  • 5,413
  • 1
  • 25
  • 34
  • 1
    I like this. Nice to see some actual testing of what would happen. It seems `push_back()` [triggers the same](http://coliru.stacked-crooked.com/a/1605bba4ad5fa792) `reserve()` behavior as `b`. – wally May 12 '16 at 20:55
  • Yes, I would have expected that. Repeated `push_back()`s are probably the most common use case for `std::vector`, and growing the capacity in exponential steps is what gives you _amortized_ O(1) complexity. – mindriot May 12 '16 at 21:00
2

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.
}
WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
  • Thanks. Does C++ 11 call it? – Hadi May 12 '16 at 20:38
  • Facebook's Folly's FBVector, a drop in replacement for `std::vector` calls `reserve` inside `resize`... https://github.com/facebook/folly/blob/master/folly/FBVector.h#L919 – WhiZTiM May 12 '16 at 20:50
  • Note, C++ is a language, STL is it's default library. Compiler products typically bundle an implementation with the actual compiler. Like, .........GCC libstdc++........... Clang --> libcxx,............ MSVC --> Dinkumware... – WhiZTiM May 12 '16 at 20:54
  • I just checked GCC 4.6's libstdc++, And yes it calls it(a variant of resize) – WhiZTiM May 12 '16 at 20:54
  • @WhiZTiM [Is STL mentioned in the C++ standard](http://stackoverflow.com/q/5205491/1460794)? :p – wally May 12 '16 at 20:59
  • @flatmouse, Ohh... Forgive my not being pedantic with words in the legalese sense... Though I view it the same thing... I meant the C++ Standard Library.. :-) ... Thanks – WhiZTiM May 12 '16 at 21:06
  • @WhiZTiM I know, I know... I just couldn't resist. Sadly a fun Q&A like the one I linked to are no longer on topic for SO. – wally May 12 '16 at 21:09