0

我正在开发一个游戏,我有一个树类。该类有一个名为“wood”的int,它保留了树中剩余的木材量。还有一个功能可以跟踪所有事件。当值达到零时,我想删除这个对象。(顺便说一下,我使用的是 CodeBlocks 和 SDL 库)

handle_events 函数:

void Tree::handle_events(SDL_Event event, int MouseX, int MouseY, int Xoffset, int Yoffset) {
if(event.type == SDL_MOUSEBUTTONDOWN) {
    if( event.button.button == SDL_BUTTON_LEFT ) {

        if((MouseX >= (xPos - Xoffset)) && (MouseX <= ((xPos + 50) - Xoffset)) && (MouseY >= (yPos - Yoffset)) && (MouseY <= ((yPos + 50) - Yoffset))) {
            selected = true;
        } else {
            selected = false;
        }
    }
}

if(wood <= 0) {
    delete this;
}

}

当我启动游戏并且“木头”归零时,树仍然在那里并且正在工作。请帮忙

编辑:

while(SDL_PollEvent(&event)) {
        MouseX = event.motion.x;
        MouseY = event.motion.y;

        menu_button.handle_button_events(event, MouseX, MouseY);
        exit_button.handle_button_events(event, MouseX, MouseY);

        for(int i = 0; i < trees.size(); i++)
        {
            trees[i].handle_events(event, MouseX, MouseY, Xoffset, Yoffset);
        }

        for(int i = 0; i < stones.size(); i++)
        {
            stones[i].handle_events(event, MouseX, MouseY, Xoffset, Yoffset);
        }

        for(int i = 0; i < bushes.size(); i++)
        {
            bushes[i].handle_events(event, MouseX, MouseY, Xoffset, Yoffset);
        }

        if(event.type == SDL_QUIT) {
            running = false;
        }

        if(event.type == SDL_KEYDOWN) {
            switch(event.key.keysym.sym) {
            case SDLK_ESCAPE:
                running = false;
            }
        }

        if(exit_button.clicked) {
            running = false;
        }

        if(menu_button.clicked) {
            paused = true;
        }


    }

Trees 是包含地图上所有树的向量

4

2 回答 2

2

trees里面有什么trees[i]?我想它是std::vector<Tree*>或类似的?

当您调用时,delete this您正在删除 引用的对象trees[i],但您没有删除向量中的条目。在删除trees[i]指向一些释放的内存之后 - 如果没有被其他东西覆盖 - 仍然看起来像一个树对象。

我建议做这样的事情:

for(int i = trees.size()-1; i >= 0; i--) {
    trees[i].handle_events(event, MouseX, MouseY, Xoffset, Yoffset);
    if (trees[i].isEmpty()) {
        delete trees[i];
        trees.erase(trees.begin()+i);
    }
}

请注意,从末尾迭代很重要,因为当元素被删除时,所有后续操作都会转移。

如果向量很大并且您进行了大量删除,请考虑使用不提供随机访问的不同结构,因为从向量中删除可能会很耗时。


更新: 我假设成员函数Tree::isEmpty()是由您实现的,其逻辑指定对象何时为空且不再需要,但并未实际删除该对象。

正如你所说,因为它treesTree对象的向量,而不是对象的指针,所以你永远不应该自己删除这些对象!向量是这些对象的所有者,它将删除它们。

出于这个原因,您应该调用trees.erase(trees.begin()+i)它,它会丢弃该对象。

于 2013-06-12T20:01:16.783 回答
1

delete this实际上并没有清理仍然存在的指向对象的指针。(它确实调用了析构函数——但是因为你有一个空的析构函数,所以这里也不会进行这样的清理。)在你之后,向量delete this中仍然会有一个(悬空!)指向已删除树的指针。trees

使用此指针的一个可能结果是树仍然出现,另一种可能是崩溃。仅使用指针无法从有效指针中区分悬空指针。

出于这个原因,delete this通常是一个坏主意,从来都不是一个简单的解决方案。

您可以考虑从调用 handle_events() 的函数中检查树是否已用完木材——然后您既可以删除树,也可以从向量中删除指针。

于 2013-06-12T19:58:31.270 回答