The problem is that this loop modifies the vector:
for (auto& entity : entities) { entity->update(); }
You iterate through it when you modify the vector to add a new element, which invalidates the iterators used to move the container.
The range-based for loop is extended by the compiler to:
auto begin = entities.begin(), end = entities.end(); for (; begin != end; ++begin) begin->update();
The call begin->update() adds a new element to the vector, which invalidates all iterators in the container, so the ++begin behavior is ++begin undefined. From a practical point of view, begin no longer points to the vector (since it redistributes and frees the old memory that begin points to), so the next call to begin->update() calls an invalid iterator, accessing the freed memory and seg-faulting.
To do this safely, you probably want to use indexes rather than iterators:
for (size_t i = 0, size = entities.size(); i != size; ++i) entities[i].update();
This fixes the size at the beginning of the cycle and therefore only iterates to the last element that exists when the cycle starts, so new elements added to the end will not be visited.
This still works when the vector changes because you do not store iterators or pointers to elements, but only an index. Until you remove elements from the vector, the index remains valid even after inserting new elements.
source share