如果对象被删除,如何从向量中删除对象

时间:2021-04-09 11:55:16

标签: c++ oop vector

我正在制作一款可供玩家射击的主机游戏。玩家按下空格键后,会创建一个新对象并将其放置在地图上,并且地图包含指向该对象的指针。这些对象存储在一个向量中。我读了一篇关于向量的文章,它说:

<块引用>

向量与动态数组相同,能够在插入或删除元素时自动调整自身大小

我以为我删除一个对象后,向量会自动缩小,所以每当其中一个射弹撞到墙上时我就这样做:

delete entities[x + y * width];
entities[x + y * width] = nullptr;

但是向量的大小没有改变。我是否需要从矢量手动删除的对象?我有一个想法,为每个存储其状态(死/活)的射弹制作一个布尔变量,以便在循环的帮助下手动将其从向量中删除。是否有这样做的更好的办法?

此外,将射弹存储在矢量中是否安全?我读到 vector 会在达到最大大小时将自身复制到内存的另一段。在那之后,我的地图中的指针会发生什么变化?

代码看起来像这样:

#include <vector>
#include <iostream>
#include <conio.h>
class Entity {
public:
    int x, y;
    int getX() { return x; }
    int getY() { return y; }
};

class Projectile : public Entity{
public:
    Projectile(int x, int y) {
        this->x = x;
        this->y = y;
    }
};
class Map {
public:
    Entity** entities;
    int width, height;
    Map(int width, int height) {
        this->width = width;
        this->height = height;
    }
    void spawn(Entity* entity) {
        entities[entity->getX() + entity->getY() * width] = entity;
    }
};

int main() {
    Map map(10, 10);
    std::vector<Projectile*> projectiles;

    map.entities = new Entity* [map.width * map.height];
    int x, y;

    while (true) {
        if (_getch() == 32) {
            std::cin >> x >> y;
            projectiles.push_back(new Projectile(x, y));
            map.spawn(*projectiles.begin());
        } 

        //...
        bool hitWall = true;

        if (hitWall) {
            delete map.entities[x + y * map.width];
            map.entities[x + y * map.width] = nullptr;
        }
    }

    return 0;
}

2 个答案:

答案 0 :(得分:2)

您需要使用迭代器。像这样:

entities.erase(entities.begin() + x + y * width)

关于安全性,对于经常实例化和销毁的小对象,最好直接存储对象而不是指针。这消除了内存泄漏或堆分配带来的悬空指针的可能性。

答案 1 :(得分:2)

从您的示例代码中,我假设您的向量定义如下:

std::vector<YourType*> entities;

因此,您的向量不包含 YourType 对象,而是包含 pointer to YourType。也就是说,vector管理的元素是指针,而不是被指向的对象。

因此,当您执行此操作 delete entities[x + y * width]; 时,您确实删除了 YourType 实例,但指针仍然存在并且它仍然在您的向量中。

如果将该语句分解为等效的 2 行,可能更容易形象化:

YourType * pointer = entities[x + y * width];
delete pointer;

要真正从向量中移除指针,你需要这样说:

entities.erase(entities.begin() + x + y * width);

这将从数组中删除指针(也将所有内容移过该索引)。您仍然需要自己执行 delete,因为向量仅管理指针,而不是 YourType


请注意,除非您有充分的理由,否则您可能不应该将指针存储在向量中,而是存储对象本身。这会消除你的困惑:

std::vector<YourType> entities;

// deleting a YourType:
entities.erase(entities.begin() + x + y * width);

不再有 deletenew,因为对象直接在向量中。因此向量会为您管理它,而不仅仅是管理指针并让您处理指向的对象。


问题编辑后更新:

在您的情况下,您确实有充分的理由,因为您实际上存储了一个非拥有指针。因此,entitiesprojectiles 存储指针可能是有意义的,因此它们实际上指向相同的对象。

所以这两个向量都将管理它们的指针,但你必须考虑这两个指针(一个来自实体的一个来自射弹的一个)的生命周期如何与对象本身交互。

删除对象不会删除两个数组中的指针。

相关问题