synaptik
synaptik

Reputation: 9499

Remove elements (and change size) of std::vector without affecting allocated memory

I'm using code such as the following:

const int MY_SIZE = 100000;
std::vector<double> v;
v.reserve(MY_SIZE);

// add no more than MY_SIZE elements to the vector

f(v);    
v.clear();

// again, add no more than MY_SIZE elements to the vector

f(v);
v.clear();

//
// etc...
//

The point of my code is to store MY_SIZE double's and then perform an operation f(std::vector<double>) on those elements. After I fill up the vector and perform the operation, I want to get rid of all the elements (and reset std::vector::size() to 0), and then add more elements. But, the key here is that I do not want to cause the space in memory allocated for the vector to be changed.

Note than I'm never going to add more than MY_SIZE elements to v, so v should never need to reallocate more memory than was allocated by v.reserve(MY_SIZE).

So, when I call v.clear() in the above code, will it affect in any way the amount of space allocated by v.reserve(MY_SIZE) or the location in memory of v.begin()?


Related question: If I call v.erase(v.begin(),v.begin()+v.size()), will it affect in any way the amount of space allocated by v.reserve(MY_SIZE) or the location in memory of v.begin()?

If I really just wanted to erase all the elements, I would call clear(). But I'm wondering about this related question because there are occasions when I need to erase only the first X elements of v, and on these occasions I want to keep the memory allocated by v.reserve(MY_SIZE) and I don't want the location of v to change.

Upvotes: 4

Views: 2859

Answers (1)

Andreas Hehn
Andreas Hehn

Reputation: 138

It seems the C++ standard (2003) implicitly guarantees that the memory is not reallocated if you call the clear() or erase() method of the std::vector.

According to the requirements of the Sequence (table 67) the a.clear() is equivalent to a.erase(begin(),end()).

Furthermore, the standard states that the erase(...) member function of the std::vector<T> does not throw an exception unless one is thrown by the copy constructor of T (section 23.2.4.3). Hence it is implicitly guaranteed, because a reallocation could cause an exception (sections 3.7.3, 20.4.1.1).

Also v.begin() remains the same, as erase(...) will only invalidate all iterators after the point of the erase (section 23.2.4.3). However, it won't be dereferenceable (since v.begin() == v.end()).

So, if you have a standard compliant implementation you are fine...

CORRECTION

My reasoning is flawed. I managed to show that erase(...) does not reallocate, but an implementation could still deallocate the memory if you erase all elements. However, if a.capacity() reports "you can add N elements without reallocating memory" after the erase/clear you are fine.

The C++11 standard defines a.clear() without referring to a.erase(...). a.clear() is not allowed to throw an exception. Hence it could deallocate, but not reallocate. So you should check the capacity after clearing the vector to make sure that the memory is still there and the next resize won't reallocate.

Upvotes: 1

Related Questions