9

I wanted to know the behavior of std::vector::reserve() in following situations:

  1. Suppose reserve(N) is called multiple times one after another immediately. Will the earlier reserve(N1) get added up or overwritten ?
  2. If the earlier reserve(N1) gets overwritten with the latest call, then what happens if the latest reserve(Nn) demands less number of slots ?
  3. After declaring vector if we have simply push_back() X elements, and then we call reserve(N). Will the already push_back() X elements counted in N ?
  4. Suppose, if the vector has some X pushed elements and now if we push_back() 1 more element (X+1), then that object would have to get relocated; but we haven't yet performed push_back(). What happens if we call reserve() now ? Will the object get relocated immediately ? If not, then how is the space reserved ?
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 1
    If you don't have a copy of the standard handy, there are [multiple](http://www.sgi.com/tech/stl/Vector.html) [references](http://en.cppreference.com/w/cpp/container/vector/reserve) online. – André Caron Feb 16 '12 at 02:58

2 Answers2

13

reserve() just makes sure that the vector's allocated memory is at least large enough to contain the number of items passed as its argument. Thus...

  1. Whichever the max value of all those passed will be the minimum resulting capacity effectively reserved.
  2. See #1.
  3. Yes.
  4. The vector allocates as much memory when reserve() is called as is necessary to store the number of items passed to reserve().

To quote from the actual standard:

void reserve(size_type n)

If n is less than or equal to capacity(), this call has no effect. Otherwise, it is a request for allocation of additional memory. If the request is successful, then capacity() is greater than or equal to n; otherwise, capacity() is unchanged. In either case, size() is unchanged.

Amber
  • 507,862
  • 82
  • 626
  • 550
  • 1
    +1 It is also important to keep in mind that if a reallocation occurs (`n` > `capacity()`); iterators, pointers and references to that vector will be invalidated. With that in mind, `reserve()` is especially useful to actually *prevent a reallocation* (and thus the invalidation of iterators, etc.) when `push_back()` is called. – netcoder Feb 16 '12 at 03:14
  • 2
    #1 is inaccurate: having _at least_ as much as `reserve()` asked means the resulting _capacity_ (not size!) might be larger than the call to `reserve()` with the largest request. – wilhelmtell Feb 16 '12 at 03:35
  • Edited "resulting size" -> "minimum resulting size". – Amber Feb 16 '12 at 08:01
  • The problem is't "minimum". You're talking about the size _of the allocated memory_, which is confusing in the presence of `vector::size()`. The canonical term for "size of allocated memory, whether used or just reserved" is `vector::capacity()`. – MSalters Feb 16 '12 at 09:33
  • If we want to be pedantic, yes. A capacity is still a size, just not a `::size()`. – Amber Feb 16 '12 at 18:19
5

Suppose reserve(N) is called multiple times one after another immediately. Will the earlier reserve(N1) get added up or overwritten ?

Unlike std::string it is not possible to call reserve() for std::vector to shrink the capacity().Calling reserve() with an argument that is less than the current capacity() is a no-op. Hence the last reserve() call which increases the current capacity will hold good.

If the earlier reserve(N1) gets overwritten with the latest call, then what happens if the latest reserve(Nn) demands less number of slots ?

Calling reserve() with an argument that is less than the current capacity() is a no-op.

After declaring vector if we have simply push_back() X elements, and then we call reserve(N). Will the already push_back() X elements counted in N ?

reserve() just allocates(reserves) enough number of elements so Yes. Note that after calling reserve() only the capacity() of the vector is changed the size() remains unaffected.If you would need to create as many elements and not just reserve memory you should be using resize().

Suppose, if the vector has some X pushed elements and now if we push_back() 1 more element (X+1), then that object would have to get relocated; but we haven't yet performed push_back(). What happens if we call reserve() now ? Will the object get relocated immediately ? If not, then how is the space reserved ?

Yes, the relocation will happen but it depends. As said before, reserve() allocates enough memory to store as many elements as the argument passed to it. So if this number of elements is greater than what can be accommodated in current vector capacity(), relocation will happen.

Standard References:
C++03 23.2.4.2 vector capacity [lib.vector.capacity]

void reserve(size_type n);

Effects: A directive that informs a vector of a planned change in size, so that it can manage the storage allocation accordingly. After reserve(), capacity() is greater or equal to the argument of reserve if reallocation happens; and equal to the previous value of capacity() otherwise. Reallocation happens at this point if and only if the current capacity is less than the argument of reserve().

Complexity: It does not change the size of the sequence and takes at most linear time in the size of the sequence.

Throws: length_error if n > max_size().248)

Notes: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. It is guaranteed that no reallocation takes place during insertions that happen after a call to reserve() until the time when an insertion would make the size of the vector greater than the size specified in the most recent call to reserve().

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533