34

I instantiate an std::vector foo(1000).

foo.size() is now 1000 and foo.capacity() is also 1000.

If I clear the vector with foo.clear(), the size() is now 0, but what is the capacity()? Does the standard say anything about that?

Alan Turing
  • 12,223
  • 16
  • 74
  • 116
  • 2
    possible duplicate of [will a call to std::vector.clear() also set the std::vector.reserve() to zero?](http://stackoverflow.com/questions/2628345/will-a-call-to-stdvector-clear-also-set-the-stdvector-reserve-to-zero) – stefan Apr 24 '14 at 15:30

4 Answers4

34

No, it doesn't. The capacity of a vector never decreases. That isn't mandated by the standard but it's so both in standard library implementations of VC++ and g++. In order to set the capacity just enough to fit the size, use the famous swap trick

vector<T>().swap(foo);

In C++11 standard, you can do it more explicitly:

foo.shrink_to_fit();
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 9
    In 0x, `vector` has `shrink_to_fit`, but the standard remarks it's non-binding, which I presume means that implementation is not required to actually do that. – Cat Plus Plus Jul 30 '11 at 11:30
  • Can you please give a c++03 quote? It says that `erase(.begin(), .end())` invalidates all iterators and references after the point of erase. That doesn't seem to say anything about the capacity. – Johannes Schaub - litb Jul 30 '11 at 11:32
  • @Johannes: I said that it's not mentioned in the standard! I said on most implementations it's so! – Armen Tsirunyan Jul 30 '11 at 11:33
  • U say that the capacity of a vector never decreases (even if no explicit call to "reserve" has happened). I cannot find the spec say so. – Johannes Schaub - litb Jul 30 '11 at 11:37
  • 1
    @Johannes: The spec ***doesn't*** say so. It just so happens to be implemented on VC++ and g++ implementations@ – Armen Tsirunyan Jul 30 '11 at 11:38
  • Ohh I see now. I was confused. – Johannes Schaub - litb Jul 30 '11 at 11:39
  • @sbi: Why? Please enlighten us :) – Armen Tsirunyan Jul 30 '11 at 11:59
  • 1
    @Armen: Yes, you cannot pass rvalues *to* swap, but you can call swap *on* rvalues, hence my swapping of the arguments :) – fredoverflow Jul 30 '11 at 12:02
  • @Fred, Armen: The vector will be shrunk, but not empty. I see now that this is what you also wrote in the accompanying text, but it's not what actually was asked. (I still think it would be a valuable additional hint (you can shrink a vector by _not_ clearing it!), but I think the original question should be answered first. (Oh, and I'd add a word about this being O(n).) – sbi Jul 30 '11 at 12:45
  • @Fred: If foo is empty, then this will make the capacity 0, no? – Armen Tsirunyan Jul 30 '11 at 12:46
  • It will make the capacity as small as the implementation deems sensible. – fredoverflow Jul 30 '11 at 12:55
  • @JohannesSchaub-litb "_U say that the capacity of a vector never decreases (even if no explicit call to "reserve" has happened). I cannot find the spec say so._" It does not work like that; which part of the spec allows the capacity to decrease? – curiousguy Jun 25 '13 at 01:22
  • @curiousguy i'm not familiar with that area of the spec anymore. but if nothing is said about the capacity value, its value is unspecified. – Johannes Schaub - litb Jun 25 '13 at 19:25
  • 1
    @JohannesSchaub-litb The spec says that after `reserve(n)` capacity is at least `n`. If nothing is said in the spec of `resize` about capacity it means that capacity is not allowed to change (unless there is a general statement that members of `vector` can shrink capacity). Unless the spec say that something can happen, it cannot happen. – curiousguy Jun 26 '13 at 02:42
  • @curious he did not call reserve – Johannes Schaub - litb Jun 26 '13 at 08:12
  • @JohannesSchaub-litb What allows `vector` to decrease capacity here? – curiousguy Jun 26 '13 at 15:15
  • @curiousguy i don't know. as i said, i am not familiar with it anymore. – Johannes Schaub - litb Jun 26 '13 at 16:07
7

To clear a vector and consume as little capacity as possible, use the swap trick:

std::vector<T>().swap(foo);

This creates an empty vector, swaps its internals with foo, and then destroys the temporary vector, getting rid of the elements that once belonged to foo and leaving foo as if it was freshly created.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • I use `std::swap(foo, ItemContainer())` and have `typedef std::vector ItemContainer` somewhere else when possible. It is more recognizable (IMHO) to have a temporary passed as an argument than having it be the calling object and an lvalue. Your way is 100% fine though. – doug65536 Nov 19 '12 at 18:52
1

No, clear doesn't affect it's capacity(), it's remain the same even if you do clear. If you want to shrink the vector to fit, you can use the following trick after calling clear: foo.swap(vector(foo));

RoundPi
  • 5,819
  • 7
  • 49
  • 75
  • 2
    It might. The standard does not specify it, so you should not rely on it. Though most implementations do it that way. – Björn Pollex Jul 30 '11 at 11:27
  • 1
    @BjörnPollex If the standard does not say that capacity can decrease, then it cannot. – curiousguy Jun 25 '13 at 01:23
  • 2
    @curiousguy: Actually if the standards don't explicitly say what happens, then it is open to happen any way the implementation wants to do it. – Zan Lynx Jul 21 '16 at 07:32
  • @ZanLynx No. The standard allows no such thing. **If the standard doesn't allow it, then it shall not happen.** – curiousguy Jul 21 '16 at 11:48
  • The standard mandates that the capacity does not change with a `clear` as `reserve` guarantees that further adding of elements do not relocate until the requested capacity is reached. This directly enforces `clear` to not reduce the capacity. – ABaumstumpf Sep 01 '22 at 08:47
1

The standard does not say anything about the effect of clear on capacity.

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • The standard guarantees that after a `reserve` adding new elements can not result in relocation until size > capacity.This indirectly restricts what `clear`is allowed to do as it must still have the same capacity, otherwise using `push_pack` would invalidate iterators it is not allowed to invalidate. – ABaumstumpf Sep 01 '22 at 08:45