在自包含向量循环中删除时"矢量迭代器不兼容"



我可以寻求帮助以确认我的问题是否来自设计问题,或者是否有针对以下问题的可能干净解决方案:

实体.h

class CLEntity3D
{
public:
    CLEntity3D();
    virtual ~CLEntity3D();
    virtual void update() = 0;
    static std::vector<CLEntity3D*> vecEntity;  
};

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

更新没问题,问题出在 ClearScene(( 上。 我得到一个"矢量迭代器不兼容"调试断言。

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

那么我的问题是:有没有办法用这种设计从CLScene中删除所有CLEntity3D对象?

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

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

问题是,在基于 for 循环的范围内,您无法从底层向量中删除任何内容。

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