Есть ли ошибка при использовании для цикла с векторами? - PullRequest
1 голос
/ 17 мая 2019

Проблема в том, что когда я делаю "for (int i = 0; i

это работает:

    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();
        }
    }

Ответы [ 3 ]

7 голосов
/ 17 мая 2019

positionsX.size() - это тип unsigned. Если он равен нулю, то вычитание 1 из него дает максимальное значение типа без знака из-за переноса и того факта, что выражение вычисляется в арифметике без знака!

Используйте

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

вместо этого ничего, что это всегда будет пропускать последний элемент в векторе. Если ты не хочешь этого, тогда брось + 1.

2 голосов
/ 17 мая 2019

Вы не указали, что означает «не работает», то есть в этом случае код не работает.

Тем не менее отвечая на ваш вопрос

Есть ли ошибка, когдаиспользуется для цикла с векторами?

Я скажу, что в коде действительно есть ошибки.

Прежде всего размер векторов определяется как целочисленный тип без знака.Тип 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

Также в циклах отсутствует последний элементvector.

Правильный цикл может выглядеть следующим образом

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

Или, по крайней мере, вы должны использовать тип size_t в качестве типа переменной i (хотя первый вариантправильнее)

for ( size_t i = 0; i < positionsX.size(); i++) {
    //...
}
2 голосов
/ 17 мая 2019

Если positionsX вектор пуст, то positionsX.size() - 1 оценивается как size_t(-1), что является очень большим положительным значением.

При преобразовании в int, как в вашем первом фрагменте, это значение будетскорее всего, поверните обратно в «-1».И тело цикла пропускается.

При использовании в сравнении i < positionsX.size() - 1 компилятор преобразует i в беззнаковое size_t, и сравнение дает значение true.Тело цикла выполнено.И он пытается получить доступ к positionsX[0], которого там нет ...

...