У этой функции есть явные возвращаемые значения на всех путях управления?
У меня есть функция Heaviside step, ориентированная на единицу для любого типа данных, который я закодировал с помощью:
template <typename T>
int h1(const T& t){
if (t < 1){
return 0;
} else if (t >= 1){
return 1;
}
}
В обзоре кода мой обозреватель сказал мне, что на всех путях управления нет явного возврата. И компилятор мне тоже не предупреждает. Но я не согласен; условия являются взаимоисключающими. Как я могу справиться с этим?
Ответы
Ответ 1
Это зависит от того, как используется шаблон. Для int
вы в порядке.
Но, если t
- это тип с плавающей запятой IEEE754 double
со значением, установленным на NaN
, ни t < 1
, ни t >= 1
не являются true
и поэтому управление программой достигает конца блока if
! Это заставляет функцию возвращаться без явного значения; поведение которого undefined.
(В более общем случае, когда t
перегружает операторы <
и >=
таким образом, чтобы не охватывать все возможности, управление программой достигнет конца блока if
без явного return
.)
Мораль этой истории здесь заключается в том, чтобы решить, какая ветка должна быть дефолтом, и сделать этот случай else
.
Ответ 2
Просто потому, что код правильный, это не значит, что он не может быть лучше. Правильное выполнение является первым шагом в качестве, а не последним.
if (t < 1) {
return 0;
} else if (t >= 1){
return 1;
}
Вышеприведенный вариант является "правильным" для любого типа данных t
, чем для нормального поведения для <
и >=
. Но это:
if (t < 1) {
return 0;
}
return 1;
Легче видеть, проверяя, что каждый случай покрыт, и избегает второго ненужного сравнения вообще (что некоторые компиляторы могут не оптимизироваться). Код не только читается компиляторами, но и людьми, включая вас через 10 лет. Дайте людям перерыв и напишите просто для их понимания.
Ответ 3
Как уже отмечалось, некоторые специальные числа могут быть как <
, так и >=
, поэтому ваш рецензент просто прав.
Вопрос: что заставило вас хотеть закодировать его таким образом, в первую очередь? Почему вы даже считаете, что жизнь так тяжела для вас самих и для других (людей, которым необходимо поддерживать ваш код)? Просто тот факт, что вы достаточно умны, чтобы вывести, что <
и >=
должны охватывать все случаи, не означает, что вам нужно сделать код более сложным, чем необходимо. Что касается физики, то и для кода тоже: сделайте все как можно проще, но не проще (я считаю, что Эйнштейн сказал это).
Подумайте об этом. Чего вы пытаетесь достичь? Должно быть что-то вроде этого: "Return 0, если вход меньше 1, в противном случае верните 1". То, что вы сделали, это добавить интеллект, сказав... о, но это означает, что я возвращаю 1, если t больше или равно 1. Этот вид ненужного "x подразумевает y" требует дополнительной мыслительной работы от имени сопровождающего. Если вы считаете, что это хорошо, я бы посоветовал сделать пару лет обслуживания кода самостоятельно.
Если бы это был мой обзор, я бы сделал еще одно замечание. Если вы используете оператор "if", вы можете в основном делать все, что хотите, во всех ветких. Но в этом случае вы ничего не делаете. Все, что вы хотите сделать, это вернуть 0 или 1 в зависимости от того, является ли t < 1 или нет. В таких случаях я думаю, что выражение??: намного лучше и читаемо, чем инструкция if
. Таким образом:
return t<1 ? 0 : 1;
Я знаю, что оператор ?:
запрещен в некоторых компаниях, и я считаю, что это ужасно. ?:
обычно лучше соответствует спецификациям, и он может сделать код намного проще для чтения (если он используется с осторожностью)...