【问题标题】:Can't delete element from vector, attempting to reference deleted function无法从向量中删除元素,试图引用已删除的函数
【发布时间】:2020-07-01 04:35:53
【问题描述】:

我正在使用 SFML 库在 C++ 中制作我的 Space Invaders 的“版本”,但是当我尝试删除一个入侵者时遇到了问题。 我的代码中有这个错误:

Enemy &Enemy::operator =(const Enemy &)': attempting to reference a deleted function

我尝试查看此论坛中推荐的其他解决方案,但我要么不理解它们,要么情况不同。

EnemyControler.cpp

EnemyControler::EnemyControler()
{
    Enemy::Type types[] = {
        Enemy::Type::Squid, Enemy::Type::Crab, Enemy::Type::Crab,
        Enemy::Type::Octopus, Enemy::Type::Octopus
    };


    for (int y = 0; y < 5; y++) { // Add enemies to the vector
        for (int x = 0; x < 11; x++){
            float enemyX = x * 40 + (gapBetweenEnemies * x * 3) + Enemy::enemyWidth; // Make horizontal gap between them
            float enemyY = y * 40 + (gapBetweenEnemies * y) + Enemy::enemyHeight; // Make vertical gap between them
            enemies.emplace_back(sf::Vector2f{ enemyX, enemyY }, types[y]); // Add them to the vector
        }
    }
}
void EnemyControler::destroyEnemy()
{
    for (auto iterator = begin(enemies); iterator != end(enemies);) {
        auto& enemy = *iterator;
        if (enemy.isAlive()) {
            iterator++;
        }
        else {
            iterator = enemies.erase(iterator);
        }
    }
}

问题出在 destroyEnemy 函数中。具体在iterator = enemies.erase(iterator);

EnemyControler.h

class EnemyControler
{
public:
    EnemyControler();

    void destroyEnemy();
private:
    const int gapBetweenEnemies = 10;

    std::vector<Enemy> enemies;
};

敌人.cpp

Enemy::Enemy(sf::Vector2f startingPosition, Type type) : 
Collidable(enemyWidth, enemyHeight), newPosition(startingPosition), enemyType(type), startingPosition(startingPosition)
{
}

敌人.h

class Enemy : public Collidable
{
public:
    enum class Type // enum for different looking enemies
    {
        Crab, Octopus, Squid
    };
    Enemy(sf::Vector2f startingPosition, Type type);

    constexpr static float enemyWidth = 30.0f;
    constexpr static float enemyHeight = 30.0f;

private:
    sf::Vector2f newPosition;
    Type enemyType;

    const sf::Vector2f startingPosition;
};

可碰撞.cpp

Collidable::Collidable(float width, float height) :
 spriteSize(width, height)
{
}

可碰撞.h

class Collidable
{
public:
    Collidable(float width, float height);
private:
    sf::Vector2f spriteSize;
};

如果没有简单的方法来解决这个问题,或者这个问题只能通过重写所有代码来解决,也许你可以建议另一种从向量中删除入侵者的方法。

【问题讨论】:

  • 此问题中显示的代码无法满足stackoverflow.com 对minimal reproducible example 的要求,因此stackoverflow.com 上的任何人都不太可能确定问题所在。这个问题必须是edited 以显示一个最小示例,不超过一两页代码(“最小”部分),任何人都可以剪切/粘贴、编译、运行和重现所描述的问题(“ reproducible”部分)完全如图所示(这包括任何辅助信息,例如程序的输入)。请参阅How to Ask 了解更多信息。

标签: c++ sfml 2d-games


【解决方案1】:

如果一个类有一个const 成员变量,那么该类operator= 的复制赋值运算符将被编译器默认删除。

来自https://en.cppreference.com/w/cpp/language/copy_assignment

如果以下任何一项为真,则将类 T 的默认复制赋值运算符定义为已删除:
- T 有一个非类类型(或其数组)的非静态数据成员,即 const;

这是因为如果类的对象包含const 成员变量,编译器无法猜测将赋值对象A 复制到对象B 中意味着什么。编译器应该忽略那个特定的成员变量吗?编译器是否应该猜测您的意思是 const,除非在复制分配时,那么这一次就可以了 - 我会换个方式看?编译器不知道你喜欢什么,所以它只是删除它。

一种选择是为您的类显式定义一个复制赋值运算符。

但是,startingPosition 已经被声明为私有,因此类之外的任何东西都不太可能无意中更改它。我建议只删除 const 说明符。

为什么复制赋值运算符很重要?我正在尝试删除东西,而不是复制分配它们

当从vector 中删除一个元素时,vector“上方”的所有元素都需要向下移动以填补空白。这通过复制赋值运算符发生。

来自https://en.cppreference.com/w/cpp/container/vector/erase

复杂性
线性:T的析构函数的调用次数与被擦除的元素个数相同,T的赋值运算符被调用的次数等于被擦除元素后向量中的元素个数

【讨论】:

  • 感谢您的快速回答!可悲的是,删除 const 或添加 static 无济于事。我编辑了答案并添加了可能有问题的 Enemy 类,因为有 constexpr 但有静态,所以我不知道。
  • 我将您的 EnemyControler 课程误读为您的 Enemy 课程。问题在于您的Enemy 类中的const sf::Vector2f startingPosition;
  • 很高兴它有帮助。你明白为什么吗?这将有助于您了解此类未来的问题。
  • 我想我明白了。但我不太确定 static 的作用。
  • 将非静态成员变量声明为 const 通常是一个错误,因为这样的问题。
猜你喜欢
  • 1970-01-01
  • 2014-06-29
  • 2014-05-05
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多