views:

85

answers:

4

I am not sure how to approach this problem:

'Player' class mantains a list of Bullet* objects:

class Player
{
protected:
    std::list< Bullet* > m_pBullet_list;
}

When the player fires a Bullet, it is added to this list. Also, inside the constructor of bullet, a reference of the same object is updated in CollisionMgr, where CollisionMgr also mantains a list of Bullet*.

Bullet::Bullet(GameGL*a_pGameGL, Player*a_pPlayer)
: GameObject( a_pGameGL )
{      
    m_pPlayer = a_pPlayer;

    m_pGameGL->GetCollisionMgr()->AddBullet(this);
}

class CollisionMgr
{

void AddBullet(Bullet* a_pBullet);

protected:
std::list< Bullet*> m_BulletPList;
}

In CollisionMgr.Update(); based on some conditions, I populate class Cell which again contain a list of Bullet*. Finally, certain conditions qualify a Bullet to be deleted. Now, these conditions are tested upon while iterating through a Cell's list. So, if I have to delete the Bullet object, from all these places, how should I do it so that there are no more dangling references to it?

std::list< Bullet*>::iterator bullet_it;

    for( bullet_it = (a_pCell->m_BulletPList).begin(); bullet_it != (a_pCell->m_BulletPList).end(); bullet_it++) {

        bool l_Bullet_trash = false;
        Bullet* bullet1 = *bullet_it;

        // conditions would set this to true

        if ( l_Bullet_Trash )
            // TrashBullet( bullet1 );
            continue;
        }

Also, I was reading about list::remove, and it mentions that it calls the destructor of the object we are trying to delete. Given this info, if I delete from one list, the object does not exist, but the list would still contain a reference to it..How do I handle all these problems ? Can someone please help me here ?

Thanks

PS: If you want me to post more code or provide explanation, please do let me know.

+3  A: 

One option is to use reference counting with weak references (Boost supports this). You have one "authoritative" container that owns the strong reference, and hence deletes any Bullet removed from it. All other containers use weak references, and remove Bullets when they find that the weak reference has become invalid.

This does complicate things slightly in several places, but it is logically much cleaner and safer than other mechanisms.

Marcelo Cantos
I somewhat understand, but can you be a bit more specific please? What would be a good keyword to search for ?
brainydexter
Have a look at Boost [shared_ptr and weak_ptr](http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm).
Marcelo Cantos
A: 

Interesting observation or maybe this is just a part of the 'undefined behavior'. So, this is how I am trashing a bullet and its not giving me an error..as of now:

void CollisionMgr::TrashBullet(Bullet* a_pBullet, Cell* a_pCell)
{

    a_pBullet->Owner()->TrashBullet( a_pBullet );
    m_BulletPList.remove( a_pBullet );
    //a_pCell->m_BulletPList.remove( a_pBullet );

    delete a_pBullet;
}

So, Once I "remove" references to Bullet from lists, I then manually delete it. What confuses me is, from the description of 'list::remove' :

void remove ( const T& value ); Remove elements with specific value. Removes from the list all the elements with a specific value. This calls the destructor of these objects and reduces the list size by the amount of elements removed.

Thus, when I call the remove on bullet from the list, the destructor for that bullet object should be called. But, that aint happening here... So, is this just a part of the undefined behavior and my compiler's quirk or am I missing something trivial here ?

brainydexter
No, the destructor should not be called. You are removing a pointer to the bullet from the list. Objects have destructors, pointers don't.
Marcelo Cantos
If the pointers point to a dynamically allocated object, it is your responsibility to call delete - but only on ONE of the pointers.
anon
The *pointer* which is contained in the container will be destructed, which is what the quote you provided indicates. The thing that the pointer points to will not be automatically destructed. You have to call deleted on the pointer exactly once. Easier is to use some sort of smart pointer to manage that for you.
Mark B
+1  A: 

You are not storing bullets in these lists, but pointers to bullets, so no destructor will be called. The objects can be safely removed from all lists, but you will need to call delete yourself.

John Allen
A: 

You can find free Smart Pointer implementation at:

www.gnotum.com

It is applicable anywhere. Get it and forget about delete statement

Irakl

irakl