Что не так с авто? - PullRequest
       10

Что не так с авто?

2 голосов
/ 25 февраля 2020
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);
}

Почему вышеуказанный цикл программы? если я поменяю auto на int все в порядке

Ответы [ 3 ]

8 голосов
/ 25 февраля 2020

arr.size() - это тип данных без знака , обычно size_t. При i без знака i >= 0 всегда равно true. Вычитание 1 из переменной без знака, равной 0, приводит к наибольшему количеству, которое может содержать тип. В результате он будет работать бесконечно.

То, что тогда произойдет, неизвестно, так как ваш индекс массива превратится в гигантское значение c, а arr[i] будет иметь неопределенное поведение для значений >= arr.size(). Если у вас есть int вместо auto, он работает, потому что i-- приведет к тому, что он в конечном итоге будет -1, и тогда i >= 0 будет false, выходя из l oop.

Объяснение этого поведения ролловера можно найти здесь :

Арифметическое целое число без знака c всегда выполняется по модулю 2 n , где n - это число битов в этом конкретном целом числе. Например, для unsigned int добавление одного к UINT_MAX дает 0, а вычитание одного из 0 дает UINT_MAX.

Так, для size_t, вычитание 1 из 0 приводит к SIZE_MAX, который обычно имеет значение 18446744073709551615.

3 голосов
/ 25 февраля 2020

В чем ваша проблема уже была решена Blaze и rafix07, но я хотел добавить, что в современном C ++ лучше по возможности использовать итераторы. Это имеет несколько преимуществ, включая переносимость кода, лучшую производительность и более читаемый код.

Ваш код может выглядеть примерно так:

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

    return arr;
}

или примерно так

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

    return arr;
}

или даже так

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

    return arr;
}
2 голосов
/ 25 февраля 2020

Если у вас есть al oop, который идет другим путем (от макс. До 0), то у вас обычно возникает эта проблема:

  • Либо максимум равен size_t, поэтому i >= 0 всегда истинно
  • Или вы изменяете i на int, чтобы у вас было сравнение со знаком и без знака, что привело бы к предупреждению компилятора, или сравнение int с большим size_t в x64.

Перепроектирование l oop:

  • Используйте новый тип для i, который будет длинным в x86 и длинным в x64, теперь i> = 0 хорошо, когда ваши объекты не выше 2 ^ 63 в x64 (скорее всего).
  • когда i == 0, разрыв внутри l oop.
  • Переход на обычный i = 0 и i < obj.size() метод.
...