arr.size() is an unsigned data type, usually size_t. With i being unsigned, i >= 0 is always true. Subtracting 1 from an unsigned variable that is 0 results in the biggest amount that the type can hold. As a result, it will cycle forever.
What then happens is uncertain, since your array index will turn into a gigantic value, and arr[i] will have undefined behavior for values >= arr.size(). If you have an int instead of auto, it works because the i-- will cause it to eventually be -1 and then i >= 0 will be false, exiting the loop.
An explanation of this rollover behavior can be found here:
Unsigned integer arithmetic is always performed modulo 2n  where n is the number of bits in that particular integer. E.g. for unsigned int, adding one to UINT_MAX gives 0, and subtracting one from 0 gives UINT_MAX.
So, for size_t, subtracting 1 from 0 results in SIZE_MAX, which commonly has a value of 18446744073709551615.