Vector erase iterator outside range [closed]

2019-08-26 08:38发布

问题:

Porting some code from my game engine from Mac to Windows in C++, and I get this runtime error: "Vector erase outside range". It works on Mac!

void Entity::runDeferreds() {
    for (auto it = deferreds.begin(); it != deferreds.end(); /* nothing */ ) {
        if (it->Condition()) {
            it->Execution();

            it = deferreds.erase(it);
        } else {
            ++it;
        }
    }
}

This iterates thru a list of "deferred" tasks, which are stored in a std::vector<DeferredCall> called deferreds. If the DeferredCall's Condition() is fulfilled, then its Execution() is run, and it should be removed from the vector. However, instead, I get the aforementioned error!

DeferredCall looks like this, not that it's too important:

struct DeferredCall {
    std::function<bool()> Condition;
    std::function<void()> Execution;
};

Help?!

EDIT:- Alternative Method

I also tried this, again working on Mac:

deferreds.erase(std::remove_if(deferreds.begin(), deferreds.end(),
    [](DeferredCall &call) {
            if (call.Condition()) {
                call.Execution();
                return true;
            }

            return false;
        }
    ), deferreds.end());

However, in this case I get "vector iterators incompatible".

回答1:

Although it doesn't answer where your error comes from, you may try to rework the code as follows:

const auto pred = [](Deferred& d){ return !d.Condition(); };
auto itMatch = std::partition( defs.begin(), defs.end(), pred);

const auto action = [](Deferred& d){ d.Execution(); };
std::for_each(itMatch, defs.end(), action);

defs.erase(itMatch, defs.end());

Also, std::vector::erase is guaranteed to return perfectly valid iterator. Could be vector::end() though.

Links: std::partition, std::for_each, std::vector::erase