• Advertisement
Sign in to follow this  

<vector> iterator access error

This topic is 2139 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am making a tower defense game and when I certain type of enemy is killed I am attempted to spawn two new enemies of a weaker type. However when I implemented this in my code I threw an access error. The code is below.

In the game loop:
//Loop through all the enemies currently active
for (EnemyArray::iterator enemy = enemies.begin(); enemy != enemies.end();)
{
enemy->update(); //update the enemy

//check if the enemy has died and can be removed
if (enemy->isDead())
enemy = enemies.erase(enemy); //remove the enemy from the array. (dont increment the iterator b/c erase returns the next position automatically
else
++enemy; //move the iterator to the next enemy
}


Then in the isDead function for the enemy i tried to do this
if(health <= 0) //was killed by the player's towers
{
playerMoney += valueWhenKilled; //get the money for killing the enemy

if(type == Black)//spawns 2 purples on death
{
enemies.push_back(Enemy(x,y,Purple));
enemies.push_back(Enemy(x,y,Purple));
}

return true; //enemy died
}


I think that this has to do with the fact that I am adding to the vector than trying to use an iterator that was created before the addition to delete something afterwards. Although that is just my guess after playing with it for a little bit, I am still fairly new to c++. As soon as I remove the push_back() lines the codes works fine, just like it did before. I am not sure what I need to do in order to get this to work.

Any suggestions?

Share this post


Link to post
Share on other sites
Advertisement
Calling push_back on a vector invalidates all iterators. You can solve this issue by using an index instead of an iterator.

Share this post


Link to post
Share on other sites

I think that this has to do with the fact that I am adding to the vector than trying to use an iterator that was created before the addition to delete something afterwards. Although that is just my guess after playing with it for a little bit, I am still fairly new to c++. As soon as I remove the push_back() lines the codes works fine, just like it did before. I am not sure what I need to do in order to get this to work.


You'd be right. You can't start looping through a vector, then add some items to it in the middle, and assume the iterators will still be valid.

I believe you have 2 options:
#1, use std::list, as I believe it allows such access as you are doing
#2, create a new vector, for new enemies to be added. Once you have completed your main game loop, add any enemies from your NewEnemiesVector to the man game Enemies vector.

Share this post


Link to post
Share on other sites
So how would i get the proper index? I don't know what spot in the array the I will be at when this need to happen. I switched to iterators from using an index and the .size() of the array because I was having problems when removing things from the array then trying to access the last elements that no longer existed.

Share this post


Link to post
Share on other sites

[quote name='bd36' timestamp='1334252194' post='4930614']
I think that this has to do with the fact that I am adding to the vector than trying to use an iterator that was created before the addition to delete something afterwards. Although that is just my guess after playing with it for a little bit, I am still fairly new to c++. As soon as I remove the push_back() lines the codes works fine, just like it did before. I am not sure what I need to do in order to get this to work.


You'd be right. You can't start looping through a vector, then add some items to it in the middle, and assume the iterators will still be valid.

I believe you have 2 options:
#1, use std::list, as I believe it allows such access as you are doing
#2, create a new vector, for new enemies to be added. Once you have completed your main game loop, add any enemies from your NewEnemiesVector to the man game Enemies vector.
[/quote]

Ok I will look into list and if it doesn't work I will use the second method because I know I will be able to get something like that to work.

Share this post


Link to post
Share on other sites
Here's some code that removes and inserts using an index:
#include <iostream>
#include <vector>

bool is_prime(unsigned long n) {
if (n <= 1)
return false;

if (n%2 == 0)
return n == 2;

for (unsigned long k=3; k*k <= n; k+=2) {
if (n%k == 0)
return false;
}

return true;
}

int main() {
std::vector<unsigned long> v;

for (int i=0; i<10; ++i)
v.push_back(i);

for (size_t i=0; i<v.size(); ) {
if (!is_prime(v))
v.erase(v.begin()+i);
else {
for (int d=0; d<10; ++d)
v.push_back(v*10+d);
++i;
}
}

for (size_t i=0; i<v.size(); ++i)
std::cout << v << '\n';
}


If erasing from the middle of the vector is going to be a common operation and you need to preserve the order, a list might be a more appropriate container. If you are going to erase from the middle of the vector but the order is irrelevant, you can remove by swapping an element with the last element and then calling pop_back.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement