2016-07-21 2 views
0

может я прошу помощи, чтобы подтвердить, если мой вопрос исходит от проблемы проектирования или если бы возможное чистое решение следующее:«Вектор итераторы несовместимыми» при удалении в себе содержал вектор петли

Entity.h

class CLEntity3D 
{ 
public: 
    CLEntity3D(); 
    virtual ~CLEntity3D(); 
    virtual void update() = 0; 

    static std::vector<CLEntity3D*> vecEntity; 
}; 

Entity.cpp

int CLEntity3D::nbrEntity = 0; 
std::vector<CLEntity3D*> CLEntity3D::vecEntity; 

CLEntity3D::CLEntity3D() 
{ 
    vecEntity.push_back(this); 
} 
CLEntity3D::~CLEntity3D() 
{ 
    vecEntity.erase((std::remove(vecEntity.begin(), vecEntity.end(), this)), vecEntity.end());  
} 

различные производный класс создается/удаление различных сущностей объекта с помощью программы, это все работает нормально.

В классе сцены, у меня есть следующие методы:

void CLScene::Update() 
{ 
    for (auto& iter : CLEntity3D::vecEntity) { 
     iter->update(); 
    } 
} 

void CLScene::ClearScene() 
{ 
    for (auto& iter : CLEntity3D::vecEntity) { 
     delete(iter); iter = nullptr; 
    } 
    CLEntity3D::vecEntity.clear(); 
} 

Update нормально, проблема с ClearScene(). Я получаю сообщение об ошибке «Нетерапевтические итераторы».

Из моих исследований, общая проблема, похоже, связана с тем, что итераторы - это разные векторы, о которых я не думаю, здесь проблема. Я думаю, что проблема заключается в том, когда вызывается ClearScene(), каждый delete (iter) изменяет размер vecEntity через деструктор CLEntity3D, поэтому делает недействительным итератор в цикле ClearScene. Я прав?

Мой вопрос будет тогда: Есть ли способ удалить все объекты CLEntity3D из CLScene с этим дизайном?

Я предполагаю, что я мог бы CLScene проведение vecEntity, который позволит устранить эту проблему, но это означало бы, что CLScene бы управлять всеми создание/удаление сущностей, поэтому не будучи столь же универсальны ...

PS: Я знаю, что этот пример не является компиляцией, но поскольку мой вопрос больше о концепции ..., пожалуйста, сообщите, если я предоставлю иначе.

+2

Проблема заключается в том, что в 'CLEntity3D', добавьте' this' в 'vecEntity' вектор, но экземпляр 'CLEntity3D' может или не может быть построен динамически (например,' CLEntity3D entity; 'против' CLEntity3D * entity = new CLEntity3D(); '). Если динамическое распределение не выполнялось, вы не можете использовать 'delete'. – Holt

+0

Я думаю, вы хотели написать '* iter = nullptr;' вместо 'iter = nullptr;', если вы измените итератор, как он должен перейти к следующему? – SHR

+0

@SHR Этот цикл 'for-range', переменная' iter' на самом деле является самим указателем, а не итератором. – Holt

ответ

1

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

Цикл в вашем методе ClearScene удаляет CLEntity3D экземпляры, которые в своем деструкторе меняют один и тот же вектор, который вы использовали в цикле for.

Относительно легко исправить было бы изменить ClearScene на что-то вроде этого:

void CLScene::ClearScene() 
{ 
    auto vectorCopy = CLEntity3D::vecEntity; 
    for (auto& iter : vectorCopy) { 
     delete iter; 
    } 
} 

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

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

Или как предложено комментарий, вы могли бы избежать копирования с помощью время цикла:

while (!CLEntity3D::vecEntity.empty()) 
{ 
    delete CLEntity3D::vecEntity.begin(); 
} 
+0

Проверьте дескриптор 'CLEntity3D', он удаляет текущий элемент из вектора. – Dutow

+0

А, я пропустил это. Я думаю, что код слишком сломан, чтобы исправить. – juanchopanza

+1

Сохраните копию: 'while (! CLEntity3D :: vecEntity.empty()) delete CLEntity3D :: vecEntity.begin();' – user4581301

Смежные вопросы