A
A
Andrey Yanduganov2015-12-04 17:23:09
C++ / C#
Andrey Yanduganov, 2015-12-04 17:23:09

How to add to std::vector while iterating?

There is a vector container. It is necessary to go through all its elements and, if a certain condition is met, add or remove elements. At the same time, at each step, you need to know about all the elements.
To make it completely clear what exactly I want to get, here is the code:

for (auto obj = Organisms.begin(); obj != Organisms.end(); obj++)
  {
    (*obj)->eat();
    (*obj)->move();
    (*obj)->reproduce();
  }

Objects can be removed in the eat function and added to the reproduce function. And in all three functions, you need to know about all existing objects.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
T
tsarevfs, 2015-12-04
@tsarevfs

Perhaps not the most elegant, but predictable enough way is to break it down into separate steps.

for (auto obj = Organisms.begin(); obj != Organisms.end(); obj++)
{
    (*obj)->eat();
}
Organisms.erase(
    std::remove_if(Organisms.begin(), Organisms.end(),
        [](organism_ptr obj){obj->is_eaten();}
        ),
    Organisms.end()
    );
organisms_t new_organisms;
for (auto obj = Organisms.begin(); obj != Organisms.end(); obj++)
{
    organism_ptr org = (*obj)->reproduce();
    if (org)
        new_organisms.push_back(org);
}
Organisms.insert(Organisms.end(), new_organisms.begin(), new_organisms.end())
for (auto obj = Organisms.begin(); obj != Organisms.end(); obj++)
{
    (*obj)->move();
}

A
Armenian Radio, 2015-12-04
@gbg

Look at the semantics of insert and erase - they also return an iterator to the newly inserted or next to the deleted element. From this and dance.

O
Oleg Tsilyurik, 2015-12-04
@Olej

What is the question?
(and what is "need to know about all existing objects." supposed to mean?)
Some of your operations will invalidate the obj iterator, then obj++ will end with... who knows what.
In such cases, it would be necessary to run the chain of iterators from the beginning, or from some fixed place earlier.
For such things, it is better (more convenient) to rewrite it all not as a for loop, but as a while loop.

V
Vitaly, 2015-12-04
@vt4a2h

Stop.
Iterating over a vector and removing/adding elements is a bad idea. The vector may well be realized and everything will end sadly. Those. the validity of iterators is not guaranteed after deletion/insertion. You can pervert of course, but it's a crutch. Either make a copy of the vector and add / remove elements, or select another container, I think that list or forward_list, or even some kind of map will do. Who knows what your job is. In any case, I am sure that this is not something highly loaded and fast, incl. The advantages of a vector for sequential iteration in the form of a cache line will not give you anything.
This is not very clear to me:
Do you have some kind of cunning iterator? Or a strange logic - who ate whom: the object itself or what? I would also understand something like this:
In any case, I advise you to think over the architecture and pay attention to design patterns like the observer and the intermediary.
PS
And the question is slightly incorrect, it seems that you are struggling with the consequences of some architectural error. Those. in fact, you don't need to remove elements from the vector when iterating. In fact, you need to ask something like this: I solve such and such a problem, I came up with a solution to it in such and such a way, but here's the bad luck ... how best to do it?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question