将 for 循环与向量一起使用时是否存在错误?

Is there a bug when using for loop with vectors?

问题是,当我执行 "for(int i = 0; i < vector.size() - 1; i++)" 时,它会给我一个 "vector subscript out of range" 错误。但是,如果我将 vector.size() - 1 放入变量中,它就可以工作。这是一个小故障还是我只是遗漏了什么?

这个有效:

    int sizePos = positionsX.size() - 1;

    for (int i = 0; i < sizePos; i++) {
        if (snake.getX() == positionsX[i] && snake.getY() == positionsY[i]) {
            gameOver = true;
            std::cout << as << std::endl;
            as++;
        }

        if (apple.getX() == positionsX[i] && apple.getY() == positionsY[i]) {
            apple.eat();
        }
    }

而这不是:

    for (int i = 0; i < positionsX.size() - 1; i++) {
        if (snake.getX() == positionsX[i] && snake.getY() == positionsY[i]) {
            gameOver = true;
            std::cout << as << std::endl;
            as++;
        }

        if (apple.getX() == positionsX[i] && apple.getY() == positionsY[i]) {
            apple.eat();
        }
    }

positionsX.size()unsigned 类型。如果它为零,则从中减去 1 会得到无符号类型的最大值,这是由于 wrap-around 以及表达式在无符号算术中求值的事实!

使用

for (std::size_t i = 0; i + 1 < positionsX.size(); i++) {

相反,这将始终忽略向量中的最后一个元素。如果你不想要那个然后删除 + 1.

如果 positionsX 向量为空,则 positionsX.size() - 1 的计算结果为 size_t(-1),这是一个非常大的正值。

当转换为 int 时,如在您的第一个代码段中,该值可能会变回“-1”。并跳过循环体。

当用于比较 i < positionsX.size() - 1 时,编译器将 i 转换为无符号 size_t 并且比较结果为真。循环体被执行。它会尝试访问不存在的 positionsX[0]...

您没有指出 "does not work" 是什么意思,在这种情况下代码不起作用。

尽管如此回答你的问题

Is there a bug when using for loop with vectors?

我会说代码确实有错误。

首先向量的大小被定义为无符号整数类型。 int类型一般不能容纳无符号整数类型的所有值。

在这个表达式中

positionsX.size() - 1

这里用到了无符号整型的运算。也就是说,表达式 positionsX.size() - 1 被转换为无符号整数类型,并且将等于该类型的最大值,前提是 positionsX.size() 等于 0。即表达式实际上计算为

static_cast<decltype( positionsX )::size_type>( positionsX.size() - 1 );

例如,对于空向量,您可以获得以下结果

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> positionsX;

    auto size = static_cast<decltype( positionsX )::size_type>( positionsX.size() - 1 );

    std::cout << size << '\n';
}

控制台输出为

18446744073709551615

第一种使用中间变量的情况

int sizePos = positionsX.size() - 1;

表达式的结果

positionsX.size() - 1

可以被截断以适应 int 类型的对象,并且相应的索引将有效(尽管范围可能完全无效,因为它可能小于实际范围)。

因此您的问题是您使用的是类型 int 而不是原始类型

decltype( positionX )::size_type

循环也省略了向量的最后一个元素。

正确的循环如下所示

for (decltype( positionX )::size_type i = 0; i < positionsX.size(); i++) {
    //...
}

或者至少你应该使用类型 size_t 作为变量的类型 i(尽管第一个变体更正确)

for ( size_t i = 0; i < positionsX.size(); i++) {
    //...
}