STL basically says: valid implementation may be stateful or stateless.
C++11 added stateful allocators as a requirement. Question is... how many years until it becomes widely available?
STL basically says: valid implementation may be stateful or stateless.
List<Zombie> zombies;
uint zcount = zombies.Count();
for (uint i = 0; i < zcount; i++)
{
uint bcount = bullets.Count();
for (uint j = 0; j < bcount; j++)
{
if (collide(bullets[j], zombies))
{
bullets.Remove(j);
zombies.Remove(i);
}
}
}
I don't use STL because I never figured out how to delete from a list while iterating through, so I made my own classes for List<>, Array<>, and Map<>
it = collection.erase(it);
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][background=rgb(250, 251, 252)]I don't use STL because I never figured out how to delete from a list while iterating through[/background]
[/font]
[/quote]
Looking at your code, you still haven't. That loop is fundamentally wrong in a number of ways. In addition to the cases Olaf highlighted, what if multiple bullets collide with a given zombie in a single frame? You'll end up removing zombies who might be nowhere near the bullet.
Standard C++ containers approach this problem by design - if using iterations, there are established idioms for erasing while iterating:
bool handleBulletCollision(vector<Bullet> &bullets, const Zombie &zombie)
{
for (auto i = bullets.begin() ; i != bullets.end() ; ++i)
{
if(collides(*i, zombie))
{
bullets.erase(i);
return true;
}
}
return false;
}
void handleZombieBulletCollisions(vector<Zombie> &zombies, vector<Bullet> &bullets)
{
auto i = zombies.begin();
while(i != zombies.end())
{
if(handleBulletCollision(bullets, *i))
{
i = zombies.erase(i);
}
else
{
++i;
}
}
}
We could re-write the latter function something like:
void handleZombieBulletCollisions(vector<Zombie> &zombies, vector<Bullet> &bullets)
{
auto end = zombies.end();
auto i = remove_if(zombies.begin(), end, [&bullets](const Zombie &zombie) {
return handleBulletCollision(bullets, zombie);
});
zombies.erase(i, end);
}
That implementation involves less copies being made if multiple zombies are removed in a single pass.
for (uint i = 0; i < list.GetCount(); i++)
{
printf("List[%i] = %i\n", i, list.Get(i));
}
for (uint i = 0; i < list.GetCount(); i++)
{
if (list.Get(i) % 2 == 0)
{
list.Remove(i);
i--;
}
}
for (uint i = 0; i < list.GetCount(); i++)
{
printf("List[%i] = %i\n", i, list.Get(i));
}
#include <vector>
#include <cstdio>
#include <cstdlib>
int main()
{
std::vector<int> numbers;
for(unsigned i = 0 ; i < 20 ; ++i)
{
numbers.push_back(std::rand() % 50);
}
for (unsigned i = 0; i < numbers.size(); i++)
{
std::printf("List[%i] = %i\n", i, numbers);
}
for (unsigned i = 0; i < numbers.size(); i++)
{
if (numbers % 2 == 0)
{
numbers.erase(numbers.begin() + i);
i--;
}
}
for (unsigned i = 0; i < numbers.size(); i++)
{
std::printf("List[%i] = %i\n", i, numbers);
}
}
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]
[background=rgb(250,251,252)]Your original posts said one should not use lists at all, not that vectors are usually better.[/background][/font]
Please quote where I said that.
[/quote]
... your linked lists, trees, etc., rather than just using LinkedList<MyClass> (or whatever the STL syntax is).
If you're worried about performance, you should strongly consider not using linked lists at all.[/quote]
(My apologies if I misinterpreted what that first quote meant.)