Archived

This topic is now archived and is closed to further replies.

AfroFire

STL Problem

Recommended Posts

Alright. I''ve run in to a problem with my STL list, and was wondering if you people could help me out. So, I have a class defined like so:
class PROJECTILE {
    public:
        PROJECTILE();
        ~PROJECTILE();
        
        void insert(Sint16 x, Sint16 y);
        
        void update();
        void draw(SDL_Surface *screen);
        
        
    private:
        list plasma; 
        list::iterator iterP;
        
        Uint8 speed;
};
 
The STL list contains a list of pointers to this class:
class PLASMA {
    public:
        PLASMA(Sint16 x, Sint16 y); /* Used to spawn bullets at the x y coords*/
        ~PLASMA();
        
        int update();
        void draw(SDL_Surface *screen);

        SDL_Rect rect_plasma;

    private:
        
        Uint8 speed;
        
        SDL_Surface *temp_plasma, *plasma_bmp;
        
        
};
 
Now, I go through my list in the projectile class function update() and update the location of the plasma projectile, and check to see if it has left the screen yet. If it has, I will return 1, and it will be removed from the list, else it shall return 0 and nothing shall happen to it.
void PROJECTILE::update() {
    iterP = plasma.begin();
    while(iterP != plasma.end()) {
        if((*iterP)->update() == 1) {
                plasma.remove(iterP);
        }
        else {
                iterP++;
        }
    }
}   
 
int PLASMA::update() {
    rect_plasma.y -= speed;
    if(rect_plasma.y <= 0) {
        return 1;
    }
    else {
        return 0;
    }
}
 
Now. The problem I run in to, is it crashes when I try to remove the object from the list (When it reaches the edge of the screen). I believe I must be doing something wrong -AfroFire

Share this post


Link to post
Share on other sites
quote:
Original post by AfroFire
In the PROJECTILE::update() function.

Ah yes, I missed that first time. There seems to be something odd about the line "plasma.remove(iterP);". list::remove() takes a value, not an iterator, so you should be dereferencing the iterator here. You also need to ensure the value is valid before calling remove(). Additionally, you might like to think about ownership of the pointees of the list pointers. Something needs to call delete on them, and you might find a ref-counted smart pointer to be of help, such as the one at Boost''s website. Out of interest, which compiler are you using?

Share this post


Link to post
Share on other sites
I think the the problem is that when you remove an object, the iterator is invalidated. (and by the way, don''t forget to delete your objects) Try something like this :


  
void PROJECTILE::update() {
iterP = plasma.begin();
while(iterP != plasma.end()) {
if((*iterP)->update() == 1) {
delete *iterP;
// If you don''t change iterP, it will crash next iteration

plasma.remove(iterP++);
}
else {
iterP++;
}
}
}

Share this post


Link to post
Share on other sites
Also, while iterating through the list, if you remove an item from that list the iterator is no longer valid.

You might need to make a copy of the list before calling the Updates.

Share this post


Link to post
Share on other sites
list::erase is the function you should use. It returns the next valid iterator so you can use this line in place of your remove (no ++ needed):
iterP = plasma.erase(iterP);



[edited by - Stoffel on July 15, 2002 11:18:14 AM]

Share this post


Link to post
Share on other sites
One thing to be careful of, is that erase only removes the element from the list, vector, map, whatever. It does not delete it, if its dynamic, so you''ll leak memory if you dont'' explicity delete it.


Cheers
Chris

Share this post


Link to post
Share on other sites
Just skimmed your code, but be careful of things like this.


SDL_Surface *temp_plasma, *plasma_bmp;


It's safer to write:


SDL_Surface *temp_plasma;
SDL_Surace *plasma_bmp;




[edited by - absolutdew on July 15, 2002 3:18:45 PM]

Share this post


Link to post
Share on other sites