Есть ли принципиальная разница: ставить или не ставить else, если в if-блоке есть return или throw?
Допустим, есть следующий код:
if (condition)
return 0;
else
DoSomething();
Его можно переписать как:
if (condition)
return 0;
DoSomething();
В обоих случаях при условии, что condition == true, будет выполнен возврат из функции, а в противном случае будет вызвана функция DoSomething(). Аналогичный пример можно привести с оператором throw вместо return. То есть логически в этих двух случаях (с else и без) разницы не будет абсолютно никакой.
Вопрос: есть ли какие-либо веские причины обязательно ставить или обязательно не ставить else в подобных ситуациях? Возможно, есть какие-то, хотя бы незначительные, различия в производительности между приведёнными двумя примерами (с else и без)?
Ответы (2 шт):
Основная разница должна быть в семантике и том, что должен понять тот, кто будет читать этот код в будущем. Все зависит от окружающего кода и вкладываемого смысла.
Если этот код записан в функции из 3 строчек и больше внутри ничего нет, то никакой особой разницы нет. Если же это функция из 5+ строк, то семантика уже проявляется (и зависит от вложенности и расположения фрагмента). Ниже речь об этом:
if A then return 0 else B;
Так скорее выглядит код внутри цикла, когда (не)найдено некоторое искомое значение и этого достаточно для определения результата функции. Или какой-то вызов метода создания/инициализации чего-либо.
if A then return 0;
Так обычно выглядят guard-statements / early-exit statements - условия проверяемые в самом начале функции, когда заранее можно определить конечный результат не выполняя основное тело функции.
Касательно Return или это Throw - не принципиально. В случае Return мы определяем "хороший" выход, а в случае Throw - "плохой".
Если в теле else выполняются действия, которые не являются валидными (например: "если речь идет только о жидких и твердых объектах и это не жидкость, то бросим в корзину для мусора"), если не выполняется условие condition (допустим оно проверяет является ли объект жидким?). Не выполнив в теле else эти действия, вы по любому выполняете их, но бросить жидкий объект в корзину нельзя, и это приводит к нарушению правил (в частности крушение программы, генерация исключения и т.д.). Написав то же самое в теле else, действия вы выполняете при условии, если condition не выполняется (не жидкий объект), и нет проблем...
Примером может являться ответ, следующего
вопроса:
template<typename ...T>
bool implic(T... args) {
if (!(std::is_integral_v<decltype(args)> && ...))
return false;
else return(args | ...);
}
Если передать в функцию не интегральный тип, то вернет ложь, а если убрать else , то специализация не компилируется, если с объектом типа невозможно выполнить битовую операцию. Так что тут else убрать нельзя.