0

Is this a good or standard practice to code like this to loop through a vector while deleting unwanted elements from it without losing performance. If there is a faster way please suggest it. This vector is of the form std::vector<AnimationState*> activeAnimations;

void AnimationPack::removeDeadAnimations() { int counter = 0; std::remove_if(activeAnimations.begin(), activeAnimations.end(), [&](AnimationState*& animation) { if (animation->isActive()) { counter++; return true; } else return false; }); activeAnimations.erase(activeAnimations.end() - counter, activeAnimations.end()); } 

Edited version

void AnimationPack::removeDeadAnimations() { activeAnimations.erase(std::remove_if(activeAnimations.begin(), activeAnimations.end(), [&](AnimationState*& animation) { if (animation->isActive()) return true; else return false; }),activeAnimations.end()); } 

Edited Code (As suggested from comments)

void AnimationPack::removeDeadAnimations() { activeAnimations.erase(std::remove_if(activeAnimations.begin(), activeAnimations.end(), [](AnimationState*& animation) { return animation->isActive(); }), activeAnimations.end()); } 
15
  • 3
    auto it = std::remove_if(v.begin(), v.end(), ...); v.erase(it, v.end()); is pretty well idiomatic – it's hard to answer without knowing what you find scary about it. Commented Jun 6, 2018 at 17:45
  • 2
    propose this code to them and take it as an opportunity to teach them about remove_if and whatever else they find confusing, this is very common. Commented Jun 6, 2018 at 17:49
  • 2
    You can probably just write return animation->isActive();. Commented Jun 6, 2018 at 17:51
  • 2
    Please do not edit the question in a way that invalidates the comments and answers. It destroys important context for future readers. If you have further questions about the "fixed" code, either post another question or append the new code at the end of the question, noting that it's a new iteration. Commented Jun 6, 2018 at 17:54
  • 3
    Note that if activeAnimations contains owning pointers you must remember to delete them yourself. If that's the case, consider using std::vector<std::unique_ptr<AnimationState>> or std::vector<AnimationState> instead. Commented Jun 6, 2018 at 18:04

2 Answers 2

2

Yes, it is called an erase-remove idiom.

Quote from Wikipedia:

The erase–remove idiom is a common C++ technique to eliminate elements that fulfill a certain criterion from a C++ Standard Library container.

erase can be used to delete an element from a collection, but for containers which are based on an array, such as vector, all elements after the deleted element have to be moved forward, to avoid "gaps" in the collection.

The algorithm library provides the remove and remove_if algorithms for this.

These algorithms do not remove elements from the container, but move all elements that don't fit the remove criteria to the front of the range, keeping the relative order of the elements. This is done in a single pass through the data range.

remove returns an iterator pointing to the first of these elements, so they can be deleted using a single call to erase.

Sign up to request clarification or add additional context in comments.

Comments

1

Removes and delete the element from the vector while iterating through it.

 void AnimationPack::removeDeadAnimations() { activeAnimations.erase(std::remove_if(activeAnimations.begin(), activeAnimations.end(), [&](AnimationState*& animation) { if (animation->isActive()) return false; else { delete animation; return true; } }), activeAnimations.end()); } 

1 Comment

You are capturing everything by reference now while in fact you don't need to capture anything in the lambda. You should change [&] to [].

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.