我可以请求帮助以确认我的问题是否来自设计问题,或者是否可能存在以下可能的清洁解决方案:
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:我知道这个例子不是一个可编译的例子,但由于我的问题更多是关于概念......请告知我是否会另外提供。答案 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();
}