Я думаю, что следующие два кода идентичны. но верхний имеет проблему C4715 «не все пути управления возвращают значение», а другой - нет. Почему появляется это предупреждение?

int func(int n){
    for(int i=0; i<1; i++){
        if(n == 0){
            return 0;
        }
        else {
            return -1;
        }
    }
}
int func(int n){
    if(n == 0){
        return 0;
    }
    else {
        return -1;
    }
}
c++
1
kims 26 Ноя 2021 в 17:02
1
Что говорится в предупреждении?
 – 
Pete Becker
26 Ноя 2021 в 17:03
1
C4715 не все пути управления возвращают значение
 – 
kims
26 Ноя 2021 в 17:04
1
Коды на самом деле не "идентичны" ??
 – 
πάντα ῥεῖ
26 Ноя 2021 в 17:04
У них одинаковое наблюдаемое поведение
 – 
Caleth
26 Ноя 2021 в 17:04
2
Компилятор недостаточно умен, чтобы разглядеть цикл. Так что во втором случае это консервативно, поскольку есть пути, по которым не может быть возврата. (Очевидно, что не на практике)
 – 
Mike Vine
26 Ноя 2021 в 17:05

3 ответа

Лучший ответ

Компилятор пытается помочь, но безуспешно. Представьте на мгновение, что код внутри цикла был просто if (n == 0) return 0;. Ясно, что когда n не равно 0, цикл выполняется один раз, а затем выполнение переходит к следующему оператору после цикла. Здесь нет оператора return, и именно об этом вас предупреждает компилятор. Просто недостаточно умен, чтобы видеть, что код внутри цикла всегда возвращается.

Так что, возможно, добавьте оператор return 0; после цикла. Это могло бы порадовать компилятор. Но это также может заставить компилятор (или какой-либо другой компилятор) выдавать другое предупреждение о «недостижимом коде», потому что этот новый оператор return фактически не может быть достигнут. Этот материал сложно анализировать, и компиляторы часто ошибаются.

4
Pete Becker 26 Ноя 2021 в 17:11
1
Я не уверен, что это не так. Если мы проигнорируем дополнительную информацию, оптимизирующий компилятор будет иметь [значения переменных, границы цикла и т. Д.], Тогда у первого есть путь через него, который не имеет возврата, а второй - нет. Так что всегда правильно предупредить в первом случае. Это очевидный пример, в котором предупреждение не требуется, но вы можете сделать вычисление границ сколь угодно сложным, пока даже самый умный компилятор не сможет с ним справиться. IMO компилятор, который предупреждает о недоступности кода после применения оптимизаций (хотя и тривиальных), неверен.
 – 
Mike Vine
26 Ноя 2021 в 17:21
Как и в этом случае, небольшие изменения в настройках оптимизации или средах могут вызвать ошибку Heisen.
 – 
Mike Vine
26 Ноя 2021 в 17:21
1
- Полностью согласен, что если бы код был другим, ответ мог бы быть другим.
 – 
Pete Becker
26 Ноя 2021 в 17:23

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

Похоже, что часть компилятора, которая выдает C4715, предполагает, что цикл for с конечным условием заканчивается в некоторых случаях, и не пытается вычислить, всегда ли он будет возвращаться раньше.

0
Caleth 26 Ноя 2021 в 17:11

Моя первая мысль, что петля не может действовать.

Вы инициализируете цикл for с помощью int i = 0, затем задаете границы i < 1 с действием, если i++

Учитывая, что i является типом int с шагом 1, он никогда не может зацикливаться.

-1
Shaun Love 26 Ноя 2021 в 17:23
4
Если бы у него не было досрочного возврата, код зацикливался бы ровно один раз. В первый раз i равен 0, поэтому он удовлетворяет i < 1.
 – 
Pete Becker
26 Ноя 2021 в 17:24