【问题标题】:Copying the address of a vector element which has to be deleted afterwards复制之后必须删除的向量元素的地址
【发布时间】:2022-10-20 18:50:29
【问题描述】:

所以我试图用 SDL2 用 C++ 制作一个游戏,但遇到了一个小问题。为了从地上捡起武器,在我检查玩家是否在对象旁边并单击“E”从不同命名空间的内联函数中捡起它之后,我必须将其地址复制到一个变量中保存在主类中并从地面删除对象,这样您就无法重新拾取它。似乎在我删除对象后,来自主类的指针从另一个对象获取值,而不是我擦除的值。

这是主类 .h 文件

class GameScene : public Scene{
public:
    GameScene();
    void init(SDL_Renderer* &renderer, int sceneIdx); //initialize variables
    void update(int &sceneIdx, double deltaTime, Vector2f screenSize); //update frame-by-frame
    void graphics(SDL_Renderer* &renderer); //render objects
    void clear(); //only called on exit
private:
    std::vector<SDL_Texture*> textures = {}; //all the textures present in the game
    std::vector<bool> movements{false, false, false, false}; //main character movements
    std::vector<Weapon> droppedWeapons = {}; //dropped pickable weapons on the ground
    std::vector<Weapon*> weapons = {nullptr, nullptr}; //slots for the primary and secondary weapon
    std::vector<Bullet> bullets = {}; //ssaves all the fired bullets on the map until deletion
    std::unordered_map<int, SDL_Rect> positionsAtlas = {}; //offsets in textures and render scales
    Cube* cube = nullptr; //main character
    int mode = 0; //0=nothing, 1=weapon --unused yet
    bool currentWeapon = 0; //saves what weapon is being used(primary or secondary)
    int mouseX, mouseY; //mouse position on screen
};

这里是函数调用.cpp 文件

WeaponActions::pickUpWeapons(cube, droppedWeapons, weapons, pickUp/*is E pressed*/, currentWeapon);

和中的功能WeaponActions 命名空间

inline void pickUpWeapons(Cube* cube, std::vector<Weapon> &droppedWeapons, std::vector<Weapon*> &weapons, bool pickUp, bool &currentWeapon)
    {
        for(unsigned int i=0;i<droppedWeapons.size();i++)
        {
            bool type = droppedWeapons[i].getType(); //type of weapon(primary or secondary)
            if(weapons[type]==nullptr && pickUp) //there is empty space in inventory
            {
                if(Math::checkCollision(cube->getPos(), cube->getScale(), droppedWeapons[i].getPos(), droppedWeapons[i].getScale())) //check if cube is near weapon
                {
                    weapons[type] = &droppedWeapons.at(i); //save address
                    droppedWeapons.erase(droppedWeapons.begin()+i); //delete element
                    currentWeapon = currentWeapon == type ? currentWeapon : type; //change current weapon if necessary
                    i--;
                }
            }
        }
    }

Weapon 对象中的 type 元素表示它是主要(步枪)还是次要(手枪)武器。 除了创建另一个对象来存储指针指向的对象之外,我应该怎么做?

【问题讨论】:

  • 您可以简单地将所有武器存储在包含所有武器数据的单个向量中,无论它是在地面上、库存中还是其他地方。只需使用指针向量或std::reference_wrappers 来存储地面上的物品列表,在库存或其他地方。请注意,您需要确保包含实际数据的向量永远不需要重新分配它的后备存储,并且永远不会移动项目以使向量中的地址保持稳定。到目前为止,最简单的方法是简单地存储指向项目的共享指针,但要注意内存碎片
  • 你知道指针不存储对象吗?它只是指向存储在其他地方的对象。
  • 我在餐巾纸上写下我的地址“123 Main St”,然后交给房地产经纪人出售。然后因为他有地址,我不再需要房子,所以我签了拆迁令。但是当房地产经纪人来看我的房子时,他说那是一堆瓦砾。我告诉他那是胡说八道——我拆掉了房子我给了他地址。
  • 在编写指向存储的指针时,您会发现类似的问题。如果您写入指针,则很可能在读回存储空间并恢复指针时,它指向的对象将消失。您几乎总是需要编写对象本身。

标签: c++ pointers sdl-2


【解决方案1】:

看起来你对内存和什么应该是指针有些困惑。我正在专门研究您如何在这里存放武器:

std::vector<Weapon> droppedWeapons = {}; //dropped pickable weapons on the ground
std::vector<Weapon*> weapons = {nullptr, nullptr}; //slots for the primary and secondary weapon

当您拾取武器时,您当前正在将指针分配到向量中武器对象的内存位置,但随后会立即移除该武器!这就是为什么你观察到你似乎装备了错误的武器。您捡起的武器已经消失,std::vector 已调整大小,并且下一个已分流以填补它的位置(std::vectors 需要将其元素保存在连续的内存中)。此操作也可能会留下一个悬空指针,例如如果您尝试拿起的武器是droppedWeapons 向量中的最后一个武器,您的weapons 指针最终将指向向量的末尾。

在不更改太多其余代码的情况下,您可以将droppedWeapons 更改为Weapon*(武器指针)的向量,而不是Weapon。然后,当您想拾取武器时,将指针分配给拾取的武器列表,如下所示:

weapons[type] = droppedWeapons.at(i); // pass weapon pointer

然后像你一样从droppedWeapons 中删除元素。

现在您正在使用指针,您必须通过使用new 分配它们来填充droppedWeapons,并在某些时候使用delete 清理所有Weapon*

在进行此更改之前,如果您还不熟悉 c++ 中的堆栈与堆内存分配,也可能是一个好主意:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-02
    • 2010-09-21
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 2012-08-20
    • 1970-01-01
    相关资源
    最近更新 更多