стирание итератора карты без вызова соответствующих деструкторов - PullRequest
1 голос
/ 25 февраля 2012

gameObjects - это std::map<sf::String,VisibleGameObject*>, а results - это std::map<sf::String,VisibleGameObject*>::iterator. Когда это работает:

return gameObjects.erase(results);

Я ожидал, что деструктор VisibleGameObject запустится, а именно:

VisibleGameObject::~VisibleGameObject(){
    m_pSceneManager->removeSprite(name);
}

никогда не запускается, пока класс, который содержит gameObjects, не будет уничтожен, который затем запускается:

GameObjectManager::~GameObjectManager(){
    std::for_each(gameObjects.begin(),gameObjects.end(),GameObjectDeallocator());
}

struct GameObjectDeallocator{
        void operator()(const std::pair<sf::String,VisibleGameObject*>&p) const{
            delete p.second;
        }
    };

тогда он работает. Почему не работает в первом случае?

Использование SFML 2.0

Спасибо

Ответы [ 2 ]

8 голосов
/ 25 февраля 2012

erase удаляет указатели из контейнера, но не вызывает delete.

Предложение:

  • измените свою карту на просто:

    std::map<sf::String,VisibleGameObject>
    

    т.е. объекты не указатели на них

или

  • используйте shared_ptr / unique_ptr (например, boost::shared_ptr или std::shared_ptr в зависимости от доступности):

    std::map<sf::String,std::shared_ptr<VisibleGameObject> >
    

    который будет вызывать деструктор

0 голосов
/ 30 ноября 2015

вызов erase () не освободит указатель, так как реализация (map) не знает, как был выделен объект, на который был указан объект ((пример: должен ли он вызывать delete или free?), И что более важно, он не владеет указатель, т.е. вы не передаете владение контейнеру при хранении указателей.

Используйте std :: unique_ptr, чтобы обернуть ваш указатель, а затем сохранить его в контейнере по значению. Это поможет собрать мусор и даст вам то, что вам нужно.

using VisibileGameObjectPtr = std::unique_ptr<VisibleGameObject>; std::map<sf::String,VisibleGameObjectPtr> gameObjects;

// memory will be automatically garbage collected when you erase this item. gameObject["key"] = VisibileGameObjectPtr(new VisibleGameObject(..args..));

...