Удалить указатель объекта, чья ссылка поддерживается в трех разных списках - PullRequest
0 голосов
/ 23 апреля 2010

Я не уверен, как решить эту проблему:

Класс 'Player' поддерживает список объектов Bullet *:

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

Когда игрок запускает Bullet, он добавляетсяв этот список.Кроме того, внутри конструктора bullet в CollisionMgr обновляется ссылка на тот же объект, где CollisionMgr также содержит список 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.Обновить();основываясь на некоторых условиях, я заполняю class Cell, которые снова содержат список Bullet *.Наконец, определенные условия определяют, что Bullet будет удален.Теперь эти условия проверяются при переборе списка ячеек.Итак, если мне нужно удалить объект Bullet из всех этих мест, как мне это сделать, чтобы больше не было висящих ссылок на него?

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;
        }

Кроме того, я читал о list :: remove , и там упоминается, что он вызывает деструктор объекта, который мы пытаемся удалить.Учитывая эту информацию, если я удалю из одного списка, объект не существует, но список будет по-прежнему содержать ссылку на него .. Как мне решить все эти проблемы?

Ответы [ 3 ]

3 голосов
/ 23 апреля 2010

Один из вариантов - использовать подсчет ссылок со слабыми ссылками (Boost поддерживает это).У вас есть один «авторитетный» контейнер, который владеет сильной ссылкой, и, следовательно, удаляет все удаленные из него маркеры.Все другие контейнеры используют слабые ссылки и удаляют маркеры, когда обнаруживают, что слабая ссылка стала недействительной.

Это несколько усложняет ситуацию в нескольких местах, но логически намного чище и безопаснее, чем другие механизмы.

0 голосов
/ 23 апреля 2010

Вы не храните маркеры в этих списках, но указатели на маркеры, поэтому деструктор вызываться не будет. Объекты можно безопасно удалить из всех списков, но вам нужно будет самим удалить их.

0 голосов
/ 23 апреля 2010

Интересное наблюдение или, возможно, это только часть «неопределенного поведения».Итак, вот как я уничтожаю пулю, и она не дает мне ошибку ... как сейчас:

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;
}

Итак, как только я "удаляю" ссылки на Bullet из списков, я тогдаудалите его вручную.Что меня смущает, так это описание «list :: remove»:

void remove ( const T& value ); Удаление элементов с определенным значением.Удаляет из списка все элементы с определенным значением.Это вызывает деструктор этих объектов и уменьшает размер списка на количество удаленных элементов.

Таким образом, когда я вызываю remove on bullet из списка, деструктор для этого объекта bullet должен вызываться,Но это не происходит здесь ... Итак, это только часть неопределенного поведения и причуды моего компилятора или я что-то упускаю здесь тривиальное?

...