4

Cppreference only says:

Removes specified elements from the container. 1) Removes the element at pos. 2) Removes the elements in the range [first; last).

Invalidates iterators and references at or after the point of the erase, including the end() iterator.

The iterator pos must be valid and dereferenceable. Thus the end() iterator (which is valid, but is not dereferencable) cannot be used as a value for pos.

The iterator first does not need to be dereferenceable if first==last: erasing an empty range is a no-op.

bartop
  • 9,971
  • 1
  • 23
  • 54
themagicalyang
  • 2,493
  • 14
  • 21
  • Looks like it does get resized: http://www.cplusplus.com/reference/vector/vector/erase/ – babu646 May 30 '18 at 08:14
  • 4
    @IanA.B.King Of course the *size* have to be changed since an element is removed, but the *capacity* doesn't have to change. – Some programmer dude May 30 '18 at 08:15
  • 1
    comparable [Does clearing a vector affect its capacity?](https://stackoverflow.com/q/6882799/6717178) It mentions: the standard does not specify this. – JHBonarius May 30 '18 at 08:16

5 Answers5

6

Not necessarily no. When reading the C++ standard (and cppreference proxies the standard remarkably well), if something is not explicitly mentioned, then assume such a something is not required.

It would possibly be sub-optimal for a C++ Standard Library implementation to do so.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • > When reading the C++ standard (and cppreference proxies the standard remarkably well), if something is not explicitly mentioned, then assume such a something is not required. So I guess the answer is it's not necessary? – themagicalyang May 30 '18 at 08:18
  • 1
    In short the answer is indeed "not necessarily". – Bathsheba May 30 '18 at 08:19
6

No. That's implied by the fact that iterators, pointers and references prior to the point of erase remain valid. Reducing the capacity would require a reallocation.

T.C.
  • 133,968
  • 17
  • 288
  • 421
4

With other constraints as complexity or iterator validity, that might force implementation in some way.

Here:

Complexity:
Linear on the number of elements erased (destructions) plus the number of elements after the last element deleted (moving).

So decreasing capacity and moving old objects is a resized buffer is not possible. Except in the case when first and begin are the same.

Decreasing just the capacity number would be possible, but I don't see any sane implementation doing that.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • "other constraints ... iterator invalidity" - the iterator being invalidated isn't a constraint. By the standard saying it's invalidated, the emphasis is that there is no requirement on the implementation to do anything to keep it valid. The implementation doesn't NEED to go out of it's way to invalidate it, because it's UB to use it - which might be .... that it works. – UKMonkey May 30 '18 at 09:17
  • @UKMonkey: I meant "which iterator should stay valid", so that if `f()` should not invalidate iterators, then reallocation could not happen. it invalidate some implementation as COW for string for example. – Jarod42 May 30 '18 at 09:34
  • Ahh - that makes much more sense :) – UKMonkey May 30 '18 at 09:35
3

The only vector operations that affect the capacity are the ones that invalidate all iterators, pointers and references, because they have reallocated the storage and moved the elements.

There is nothing in the Allocator concept that would allow it to change the allocation size in place, so the capacity can't change in that manner either.

In theory an implementation could specialise on std::allocator and reallocate, under the "As-if" rule, but I doubt there are any serious implementations that would do such a thing.

Caleth
  • 52,200
  • 2
  • 44
  • 75
3

A quick example could have cleared your doubt :( compiled using VS2017 )

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> intVec{ 1,2,3,4,5,6,7,8,9,10 };
    std::cout << "Capacity and size before erase : " << intVec.capacity() << ", "<< intVec.size() << std::endl;
    intVec.erase(intVec.begin() + 3);
    std::cout << "Capacity and size after erase : " << intVec.capacity() << ", " << intVec.size() << std::endl;
    return 0;
}

Output :

Capacity and size before erase : 10, 10

Capacity and size after erase : 10, 9

Note that while capacity() doesn't decrease after the erase, the size() certainly does.

Vishaal Shankar
  • 1,648
  • 14
  • 26