离开成功使用 std::erase 的方法后删除了错误的元素

Wrong element is removed after leaving method which used std::erase succesfully

我正在研究图形引擎。引擎有 std::vector 个可绘制对象。 Drawable 是一个包含 Model 和 DrawableObject 的对象,DrawableObject 又包含着色器程序和来自 2D 或 3D 模型的一堆顶点。添加新的 Drawable 很顺利,当我尝试删除 Drawable 时出现问题。最后一个 Drawable 将始终被删除,倒数第二个将更改其值。

代码

Drawable.h

class Drawable
{
public:
    Drawable& operator=(const Drawable& other)
    { 
        Drawable tmp(other);
        std::swap(model, other.model);
        std::swap(drawableObject, other.drawableObject);
        return *this;
    }

    Drawable(domain::Model& model, DrawableObject& drawableObject) :
        model(model),
        drawableObject(drawableObject)
    {}

    domain::Model& model;
    DrawableObject& drawableObject;
};

game.cpp

void Game::init_game()
{
    human = domain::Model(glm::vec3(0, 0, -3));
    moveables.push_back(&human);
    room = domain::Model(glm::vec3(0, 0, -10));
    props.push_back(&room);
    cube = domain::Model(glm::vec3(0, 0, 0));
    props.push_back(&cube);
}

void Game::init_graphics_engine()
{
    // ... load graphics models

    // add drawables
    graphicsEngine->add(cube, Drawable::CUBE);
    graphicsEngine->add(human, Drawable::HUMAN);
    graphicsEngine->add(room, Drawable::ROOM);
    graphicsEngine->add(topDownScene->cursor, Drawable::MARKER);
}

graphics_engine/engine.cpp

void Engine::add(domain::Model& model, unsigned int object)
{
    auto drawableObject = drawableObjects[object];
    // make sure not to add a model that already is represented
    auto it = std::find_if(drawables.begin(), drawables.end(), [&model](Drawable& drawable) {return &drawable.model == &model;});
    if(drawableObject && it == drawables.end())
        drawables.push_back(Drawable(model, *drawableObject));
}

void Engine::remove(domain::Model& model)
{
    auto predicate = [&model](Drawable& drawable) 
    {
        return &drawable.model == &model;
    };
    drawables.erase(std::remove_if(drawables.begin(), drawables.end(), predicate), drawables.end());
}

场景

这是我启动应用程序时的场景:

这是尝试擦除中间的小 'human' 立方体后的场景:

代码删除了最后一个 Drawable,即白色标记,而不是 'human' 立方体,并更改了房间的 z 位置。这几乎总是发生,它删除了最后一个元素并将第二个元素的 z 更改为倒数第二个。仅当我在 init 方法中最后添加 'human' 多维数据集时才有效。

断点

删除对象之前:

删除对象后:

这是正确的。

离开移除方法并查看渲染循环:

不知何故改变了。

我将 class 成员更改为指针。现在可以了。评论是对的,我没有对tmp变量做任何事情。

class Drawable
{
public:
    Drawable& operator=(const Drawable& other)
    { 
        this->model = other.model;
        this->drawableObject = other.drawableObject;
        return *this;
    }

    Drawable(domain::Model* model, std::shared_ptr<DrawableObject> drawableObject) :
        model(model),
        drawableObject(drawableObject)
    {}

    domain::Model* model;
    std::shared_ptr<DrawableObject> drawableObject;
};