Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is wrong with auto?

Tags:

c++

vector

auto

vector<int> function(vector<int> &arr)
{
    for(auto i = arr.size() - 1; i >= 0; i--)
        std::cout << arr[i] << " ";

    return arr;
}

int main()
{
    vector<int> arr{1,2,3,4};
    function(arr);
}

Why does the above program cycle? if I change auto with int everything is ok

like image 255
Ionut Alexandru Avatar asked Mar 11 '26 15:03

Ionut Alexandru


2 Answers

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.

like image 192
Blaze Avatar answered Mar 14 '26 05:03

Blaze


What is you problem was already answered by Blaze and rafix07, but I wanted to add that in modern C++ its better to use iterators whenever possible. This has few advantages including code portability, better performance and more readable code.

Your code can look something like this:

std::vector<int> function(std::vector<int> &arr)
{
    for(auto it = arr.rbegin(); i != arr.rend(); ++i)
        std::cout << *it << " ";

    return arr;
}

or like this

std::vector<int> function(std::vector<int> &arr)
{
    std::for_each(arr.rbegin(), arr.rend(), [](int val) {
        std::cout << val << " ";
    });

    return arr;
}

or even like this

std::vector<int> function(std::vector<int> &arr)
{
    std::copy(arr.rbegin(), arr.rend(), std::ostream_iterator<int>(std::cout, " "));

    return arr;
}
like image 38
sklott Avatar answered Mar 14 '26 03:03

sklott