我可以寻求帮助以确认我的问题是否来自设计问题,或者是否有针对以下问题的可能干净解决方案:
实体.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();
}