I have a vector containing n complex objects. I want to perform a significant number of erasure, which would be extremely inefficient using .erase(). The way I thought I would do it is by creating an empty vector on the heap, filling it with copies of objects that are to be kept, and redirecting the original vector towards the new one, without a copy. And of course free the old .data().
Something like this:
vector<Obj>* newVptr = new vector<Obj>;
newVptr->reserve(newSize);
int newId = 0;
for (int i = 0; i < oldSize; i++) {
if (isKept(oldV[i])) {
(*newVptr)[newId] = oldV[i]; // deep copy of Obj
newId++;
}
}
then free oldV's array (.data()) and replace the internal pointer with newVptr. How ?
I cant just discard oldV and keep going with newV, as it is an attribute of a class.
There's almost never a need to allocate a std::vector
dynamically, as they allocate dynamically internally.
If you erase one-by-one, then that will be inefficient, yes. But the usual way to do this is using one of the std::remove*
algorithms to move all the elements you want to keep to the front of the vector
, and then call erase on the end.
For example:
oldV.erase(std::remove_if(oldV.begin(), oldV.end(), std::not_fn(isKept)),
oldV.end());
Or in C++20:
std::erase_if(oldV, std::not_fn(isKept));
If you really want to copy the kept elements instead you could do:
std::vector<Obj> newV;
newV.reserve(oldV.size());
std::copy_if(oldV.begin(), oldV.end(), std::back_inserter(newV), isKept);
oldV = std::move(newV);
That std::move
at the end would do the equivalent of your pointer swap idea.