2

Is there a way to clear the contents of std::vector while retaining the memory allocation?

The reason for this is that I have a section of code which loops, and I wish to optimize this. I currently have data stored in std::vectors. Each time the loop begins the contents of the vector should be cleared. I then use push_back to enter data into the vector, however since the length of the vector does not often change between iterations of the loop, I would ideally like the vector to retain its allocated storage in memory.

If this is not possible with vector is it possible with another fast access STD type?

FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225

2 Answers2

7

Is there a way to clear the contents of std::vector while retaining the memory allocation?

Yes you call std::vector::clear() method, as it is stated in documentation:

Leaves the capacity() of the vector unchanged

Slava
  • 43,454
  • 1
  • 47
  • 90
  • 2
    woah cppreference links to a SO answer. Quite unexpected that is. – 463035818_is_not_an_ai Sep 18 '20 at 17:42
  • Ah, I must have misread the documentation. I thought it said that `clear()` reduces capacity to zero - but it seems I confused size with capacity. – FreelanceConsultant Sep 18 '20 at 18:08
  • 2
    I think cppreference might be wrong on this count. It's definitely true in practice, but I'm not that the behavior is actually required. The note you cite on cppreference refers back to an SO answer which isn't very convincing because it seems to assume the conclusion. It all rests on a requirement in [vector::reserve](https://timsong-cpp.github.io/cppwp/vector#capacity-7) but the interpretation of that passage that is used to justify `capacity` not changing in `clear` seems flimsy. I find all this a little bit surprising. I thought this rule was clear in the standard but it isn't. – François Andrieux Sep 18 '20 at 18:22
0

First have look at here:

Does clearing a vector affect its capacity?

So the standard does not seem to mandate that the capacity is unchanged after clear. But it usually does so in practice.

You can do two things however:

  1. use reseve on the vector at the beginning of the loop, so that you only have one allocation per loop. This is quite simple.
  2. You can use your vector in an indexed way. This seems to be more optimal, but harder to do.

UPDATE: problem with the answer provided here:

What does the standard say about how calling clear on a vector changes the capacity?

The justification in the answer is based on this: No reallocation shall take place during insertions that happen after a call to reserve() until an insertion would make the size of the vector greater than the value of capacity().

This is in the C++ standard.

You can try this:

v.reserve(v.capacity());
v.clear();

However the standard does not specify if the capacity is changed by clear, nor does it specify if the clause for reserve refers to the capacity at the time of the reseve call, or at the time of insert.

UPDATE: for a relevant discussion about this issue on the C++ standards comittee discussion board, please see this: https://cplusplus.github.io/LWG/issue1102

g_bor
  • 1,077
  • 6
  • 14
  • 1
    this answer claims that capacity is guaranteed to not change: https://stackoverflow.com/questions/18467624/what-does-the-standard-say-about-how-calling-clear-on-a-vector-changes-the-capac/18467916#18467916 – 463035818_is_not_an_ai Sep 18 '20 at 17:45
  • 1
    @idclev463035818 There is no such guarantee that I can find. From the [C++11 standard](https://timsong-cpp.github.io/cppwp/n3337/sequence.reqmts#4) up to the [C++20 standard](https://timsong-cpp.github.io/cppwp/n4861/sequence.reqmts#4), the `clear` function is only bound by the requirements of the SequenceContainer concept -- and this only requires that elements are destroyed, and that complexity is linear. No such passage _restricts_ capacity from changing – Human-Compiler Sep 18 '20 at 18:04
  • Technically it's unspecified if capacity is allowed to change, which doesn't make it invalid to do so as far as I understand – Human-Compiler Sep 18 '20 at 18:05
  • @Human-Compiler I am also not convinced by that answer. The cppreference page for `std::vector::clear` links to that answer. That of course doesn't mean that it is correct, but my search for the truth ended in a circle so I didn't look further.... – 463035818_is_not_an_ai Sep 18 '20 at 18:06
  • I was prompted to look by the cppreference article/stack overflow link as well, expecting to be in agreement that `clear` doesn't change the capacity... At this point I'm under the impression that it's unspecified -- although all known implementations don't actually change capacity. I know that there is generally an assumption on "observable side-effects", but `insert`/`erase` never indicate `size()` changing as observable effects either – Human-Compiler Sep 18 '20 at 18:08
  • @Human-Compiler i cannot imagine a good reason why capacity should change, so without further searching I also assume it is unspecified. – 463035818_is_not_an_ai Sep 18 '20 at 18:17
  • 1
    @Human-Compiler The definition of `size` requires that it changes when `insert` and `erase` happen. It is the defined to be `std::distance(a.begin(), a.end())` and both `insert` and `erase` change that range. Edit : Though it is true that there is no such general definition for the concept of `capacity`, only `capacity()` defines that term. So it could change for any reason as long as it doesn't violate other requirements. – François Andrieux Sep 18 '20 at 18:24
  • I guess I will just ask for clarification. In the current version this is not specified, but maybe it should be. – g_bor Sep 18 '20 at 18:28