I have an std::vector of objects and i cycle it calling some methods of the object. One of them will check a particular condition and if needed will delete itsef from the vector. The point is that erasing the element invalidate the iterator and I cannot continue the loop of it. I found boost::shared_ptr and boost::weak_ptr, could these fix the problem deleting the object after calling all methods and after incremented the iterator? If so, how?
EDIT 1
class CPippo
{
public:
void Pippo();
void Pippo2();
}
class CPippoManager
{
public:
void PipppManager();
void RemovePippo(CPippo *pippo);
private:
std::vector<CPippo*> pippoVector;
}
void CPippo::Pippo()
{
...
if (condition)
{
pippoManager->RemovePippo(this);
}
}
void CPippo::Pippo2()
{
...
}
void CPippoManager::RemovePippo(CPippo *pippo)
{
this->pippoVector.erase(this->pippoVector.begin(), this->pippoVector.end(), pippo);
}
void CPippoManager::PipppManager()
{
for (std::vector<CPippo*>::iterator it = this->pippoVector.begin(); it != this->pippoVector.end; ++it)
{
(*it)->Pippo();
(*it)->Pippo2();
}
}
Never mind what your vector contains - the deletion of managed resources can indeed be left to smart pointers, but the more pressing issue is how to manipulate the container itself.
std::vector
indeed has very poor iterator invalidation: erasing or inserting invalidates all iterators from the erasee/insertee onwards, so you cannot even use the standard earase(it++)
idiom. But neither should you, since erasing from a vector is expensive. The better solution is to use remove/erase and supply a functor that checks the condition for erasure, and then erase everything in one wash:
std::vector<T> v;
v.erase(std::remove_if(v.begin(), v.end(), MyPred), v.end());
Here MyPred
is a predicate that implements your criterion. In C++11 this could be a handy lambda.
If your existing algorithm is too involved, perhaps you can adapt the idea of remove
in your own algorithm and move the to-be-erased object to the back of the vector with swap
, and return the iterator past the last good element at the end of the algorithm. Then you can have your own optional clean-up loop on the range of objects to be deleted, and then call erase
on that range.