【问题标题】:deleting object in member function inside class删除类内成员函数中的对象
【发布时间】:2013-06-12 19:40:51
【问题描述】:

我正在开发一个游戏,我有一个树类。该类有一个名为“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 是包含地图上所有树的向量

【问题讨论】:

  • 你能展示将 SDL_Event 传递给Tree::handle_events() 的代码吗?你有析构函数吗,Tree::~Tree()
  • 你确定你调用了这个方法吗?
  • 我有一个空的析构函数 Tree::~Tree(){ }。至于在事件中传递的代码,它位于主游戏循环中。一会就贴出来
  • 这段代码位于主循环中
  • while(SDL_Pol...){} 不是主循环。它位于主循环的一侧。

标签: c++ class object this delete-operator


【解决方案1】:

trees[i] 中的trees 是什么?我猜是std::vector&lt;Tree*&gt; 或类似的?

当您调用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),它会丢弃该对象。

【讨论】:

  • trees 是地图上所有树对象的向量。这显示了 2 个错误:|272|error: 'class Tree' has no member named 'isEmpty'|和 |273|错误:类型为“删除”的“类树”参数,预期指针|
  • 好吧......它也不起作用。树保持在原来的位置 编辑:我在 if 中写了 '=' 而不是 '=='。现在它完美地工作了。非常感谢!
【解决方案2】:

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

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

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

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

【讨论】:

  • 这个语法是否可以用于删除树对象:trees[i].~Tree();
  • 不,这是对析构函数的显式调用,它不能解决任何问题。问题不在于该对象没有被正确删除——它是。问题是您仍然保留指向它曾经所在位置的指针。查看vector 的文档(或其他答案),了解如何从向量中删除元素(例如从向量 中的Tree*)。
猜你喜欢
  • 1970-01-01
  • 2013-07-28
  • 2013-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
相关资源
最近更新 更多