Search code examples
c++loopsvectorunsigned-integerinteger-arithmetic

Is there a bug when using for loop with vectors?


The problem is that when i do "for(int i = 0; i < vector.size() - 1; i++)", it gives me a "vector subscript out of range" error. However if I put the vector.size() - 1 in a variable, it works. Is this a glitch or am I just missing something?

this works:

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

and this does not:

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

Solution

  • You did not point out what means "does not work" that is in which case the code does not work.

    Nevertheless answering your question

    Is there a bug when using for loop with vectors?

    I'll say that the code indeed has bugs.

    First of all the size of vectors is defined as unsigned integral type. The type int in general can not accomodate all values of the unsigned integral type.

    In this expression

    positionsX.size() - 1
    

    there is used the arithmetic of unsigned integral types. That is the expression positionsX.size() - 1 is converted to the unsigned integral type and will be equal to the maximum value for the type provided that positionsX.size() is equal to 0. That is the expression in fact evaluates as

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

    For example for an empty vector you can get the following result

    #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';
    }
    

    The console output is

    18446744073709551615
    

    In the first case when an intermediate variable is used

    int sizePos = positionsX.size() - 1;
    

    the result of the expression

    positionsX.size() - 1
    

    can be truncated to fit an object of type int and corresponding indices will be valid (though the range can be in whole invalid that is it can be less than the actual range).

    Thus your problem is that you are using the type int instead of the original type

    decltype( positionX )::size_type
    

    Also the loops omit the last element of the vector.

    The correct loop can look the following way

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

    Or at least you should use the type size_t as the type of the variable i (though the first variant is more correct)

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