在自包含向量循环中删除时,“向量迭代器不兼容”

时间:2016-07-21 06:25:58

标签: c++ vector iterator

我可以请求帮助以确认我的问题是否来自设计问题,或者是否可能存在以下可能的清洁解决方案:

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

各种派生类正在通过程序创建/删除不同的实体对象,这一切都正常。

在Scene类中,我有以下方法:

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

更新没问题,问题出在ClearScene()上。我得到了一个“Vector Iterators不兼容”调试断言。

从我的研究中,常见的问题似乎是因为迭代器来自不同的向量,我认为这不是问题所在。我认为问题是当调用ClearScene()时,每个delete(iter)都会通过CLEntity3D析构函数更改vecEntity的大小,从而使ClearScene循环中的迭代器无效。我是对的吗?

我的问题是: 有没有办法从该设计中删除CLScene中的所有CLEntity3D对象?

我想我可以让CLScene持有vecEntity,这可以消除问题,但这意味着CLScene必须管理所有实体的创建/删除,因此不是那么多功能......

PS:我知道这个例子不是一个可编译的例子,但由于我的问题更多是关于概念......请告知我是否会另外提供。

1 个答案:

答案 0 :(得分:1)

问题是,在基于循环的范围内,你无法从底层矢量中删除任何东西。

ClearScene方法中的循环会删除CLEntity3D个实例,其中的析构函数会更改您在for循环中使用的相同向量。

相对简单的解决方法是将ClearScene更改为以下内容:

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

这是有效的,因为循环在副本上运行,并且删除发生在原始文件上。

请注意,循环后无需清除原始向量,因为析构函数确保在删除每个项目后向量将为空。

或者根据评论的建议,您可以使用while循环来避免复制:

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